Browse Source

clearly separate usage of statvfs from stat for file existance

Used statvfs to also check for existance vs lstat. On dead symlinks
this resulted in ENOENT making certain functions fail.

closes #239
pull/242/head
Antonio SJ Musumeci 9 years ago
parent
commit
4ecf3c5797
  1. 80
      src/fs.cpp
  2. 27
      src/fs.hpp
  3. 30
      src/policy_all.cpp
  4. 97
      src/policy_eplfs.cpp
  5. 90
      src/policy_epmfs.cpp
  6. 2
      src/policy_erofs.cpp
  7. 59
      src/policy_ff.cpp
  8. 2
      src/policy_invalid.cpp
  9. 91
      src/policy_lfs.cpp
  10. 81
      src/policy_mfs.cpp
  11. 19
      src/policy_newest.cpp

80
src/fs.cpp

@ -52,33 +52,33 @@ namespace fs
} }
bool bool
exists(const string &path,
struct statvfs &st)
exists(const string &path)
{ {
int rv;
rv = ::statvfs(path.c_str(),&st);
struct stat st;
return STATVFS_SUCCEEDED(rv);
return exists(path,st);
} }
bool bool
exists(const string &path)
statvfs(const string &path,
struct statvfs &st)
{ {
struct stat st;
int rv;
return exists(path,st);
rv = ::statvfs(path.c_str(),&st);
return STATVFS_SUCCEEDED(rv);
} }
bool bool
exists(const string &path,
bool &readonly,
size_t &spaceavail)
info(const string &path,
bool &readonly,
size_t &spaceavail)
{ {
bool rv; bool rv;
struct statvfs st; struct statvfs st;
rv = exists(path,st);
rv = fs::statvfs(path,st);
if(rv) if(rv)
{ {
readonly = StatVFS::readonly(st); readonly = StatVFS::readonly(st);
@ -89,33 +89,28 @@ namespace fs
} }
bool bool
exists_on_rw_fs(const string &path,
struct statvfs &st)
readonly(const string &path)
{ {
int rv;
bool rv;
struct statvfs st;
rv = ::statvfs(path.c_str(),&st);
rv = fs::statvfs(path,st);
return (STATVFS_SUCCEEDED(rv) && !StatVFS::readonly(st));
return (rv && StatVFS::readonly(st));
} }
bool bool
exists_on_rw_fs(const string &path)
spaceavail(const string &path,
size_t &spaceavail)
{ {
bool rv;
struct statvfs st; struct statvfs st;
return exists_on_rw_fs(path,st);
}
bool
exists_on_rw_fs_with_at_least(const string &path,
const size_t minfreespace)
{
struct statvfs st;
rv = fs::statvfs(path,st);
if(rv)
spaceavail = StatVFS::spaceavail(st);
return (exists_on_rw_fs(path,st)
&&
StatVFS::spaceavail(st) >= minfreespace);
return rv;
} }
void void
@ -224,20 +219,18 @@ namespace fs
string &path) string &path)
{ {
fsblkcnt_t mfs; fsblkcnt_t mfs;
fsblkcnt_t spaceavail;
const string *mfsbasepath; const string *mfsbasepath;
mfs = 0; mfs = 0;
mfsbasepath = NULL; mfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
struct statvfs st;
size_t spaceavail;
const string &basepath = basepaths[i]; const string &basepath = basepaths[i];
if(!fs::exists(basepath,st))
if(!fs::spaceavail(basepath,spaceavail))
continue; continue;
spaceavail = StatVFS::spaceavail(st);
if(spaceavail < minfreespace) if(spaceavail < minfreespace)
continue; continue;
if(spaceavail <= mfs) if(spaceavail <= mfs)
@ -254,23 +247,4 @@ namespace fs
return 0; return 0;
} }
bool
available(const string &path,
const bool needswritablefs,
struct statvfs &st)
{
return (needswritablefs ?
fs::exists_on_rw_fs(path,st) :
fs::exists(path,st));
}
bool
available(const string &path,
const bool needswritablefs)
{
return (needswritablefs ?
fs::exists_on_rw_fs(path) :
fs::exists(path));
}
}; };

27
src/fs.hpp

@ -28,19 +28,19 @@ namespace fs
bool exists(const string &path, bool exists(const string &path,
struct stat &st); struct stat &st);
bool exists(const string &path,
struct statvfs &st);
bool exists(const string &path); bool exists(const string &path);
bool exists(const string &path,
bool &readonly,
size_t &spaceavail);
bool exists_on_rw_fs(const string &path,
struct statvfs &st);
bool exists_on_rw_fs(const string &path);
bool statvfs(const string &path,
struct statvfs &st);
bool info(const string &path,
bool &readonly,
size_t &spaceavail);
bool readonly(const string &path);
bool exists_on_rw_fs_with_at_least(const string &path,
const size_t minfreespace);
bool spaceavail(const string &path,
size_t &spaceavail);
void findallfiles(const vector<string> &srcmounts, void findallfiles(const vector<string> &srcmounts,
const char *fusepath, const char *fusepath,
@ -61,13 +61,6 @@ namespace fs
int mfs(const vector<string> &srcs, int mfs(const vector<string> &srcs,
const size_t minfreespace, const size_t minfreespace,
string &path); string &path);
bool available(const string &path,
const bool needswritablefs);
bool available(const string &path,
const bool needswritablefs,
struct statvfs &st);
}; };
#endif // __FS_HPP__ #endif // __FS_HPP__

30
src/policy_all.cpp

@ -29,15 +29,21 @@ using std::size_t;
static static
int int
_all_create(const vector<string> &srcmounts,
_all_create(const vector<string> &basepaths,
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
const string *basepath = &srcmounts[i];
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i];
if(!fs::exists_on_rw_fs_with_at_least(*basepath,minfreespace))
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(spaceavail < minfreespace)
continue; continue;
paths.push_back(basepath); paths.push_back(basepath);
@ -51,15 +57,15 @@ _all_create(const vector<string> &srcmounts,
static static
int int
_all(const vector<string> &srcmounts,
const char *fusepath,
vector<const string*> &paths)
_all_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
string fullpath; string fullpath;
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
const string *basepath = &srcmounts[i];
const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
@ -79,14 +85,14 @@ namespace mergerfs
{ {
int int
Policy::Func::all(const Category::Enum::Type type, Policy::Func::all(const Category::Enum::Type type,
const vector<string> &srcmounts,
const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
if(type == Category::Enum::create) if(type == Category::Enum::create)
return _all_create(srcmounts,minfreespace,paths);
return _all_create(basepaths,minfreespace,paths);
return _all(srcmounts,fusepath,paths);
return _all_other(basepaths,fusepath,paths);
} }
} }

97
src/policy_eplfs.cpp

@ -15,75 +15,116 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp" #include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
using std::size_t; using std::size_t;
using mergerfs::Policy;
using mergerfs::Category; using mergerfs::Category;
static static
void
_calc_lfs(const struct statvfs &st,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &lfs,
const string *&lfsbasepath)
int
_eplfs_create(const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
vector<const string*> &paths)
{ {
fsblkcnt_t spaceavail;
string fullpath;
size_t eplfs;
const string *eplfsbasepath;
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail < lfs))
eplfs = std::numeric_limits<size_t>::max();
eplfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
lfs = spaceavail;
lfsbasepath = basepath;
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath);
if(!fs::exists(fullpath))
continue;
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(spaceavail < minfreespace)
continue;
if(spaceavail > eplfs)
continue;
eplfs = spaceavail;
eplfsbasepath = basepath;
} }
if(eplfsbasepath == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(eplfsbasepath);
return POLICY_SUCCESS;
} }
static static
int int
_eplfs(const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths)
_eplfs_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
string fullpath; string fullpath;
struct statvfs st;
fsblkcnt_t eplfs;
size_t eplfs;
const string *eplfsbasepath; const string *eplfsbasepath;
eplfs = -1;
eplfs = std::numeric_limits<size_t>::max();
eplfsbasepath = NULL; eplfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
size_t spaceavail;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
if(!fs::available(fullpath,needswritablefs,st))
if(!fs::exists(fullpath))
continue;
if(!fs::spaceavail(*basepath,spaceavail))
continue;
if(spaceavail > eplfs)
continue; continue;
_calc_lfs(st,basepath,minfreespace,eplfs,eplfsbasepath);
eplfs = spaceavail;
eplfsbasepath = basepath;
} }
if(eplfsbasepath == NULL) if(eplfsbasepath == NULL)
return (errno=ENOENT,POLICY_FAIL);
return POLICY_FAIL_ENOENT;
paths.push_back(eplfsbasepath); paths.push_back(eplfsbasepath);
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
static
int
_eplfs(const Category::Enum::Type type,
const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
vector<const string*> &paths)
{
if(type == Category::Enum::create)
return _eplfs_create(basepaths,fusepath,minfreespace,paths);
return _eplfs_other(basepaths,fusepath,paths);
}
namespace mergerfs namespace mergerfs
{ {
int int
@ -94,12 +135,8 @@ namespace mergerfs
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv; int rv;
const bool needswritablefs =
(type == Category::Enum::create);
const size_t minfs =
((type == Category::Enum::create) ? minfreespace : 0);
rv = _eplfs(basepaths,fusepath,minfs,needswritablefs,paths);
rv = _eplfs(type,basepaths,fusepath,minfreespace,paths);
if(POLICY_FAILED(rv)) if(POLICY_FAILED(rv))
rv = Policy::Func::lfs(type,basepaths,fusepath,minfreespace,paths); rv = Policy::Func::lfs(type,basepaths,fusepath,minfreespace,paths);

90
src/policy_epmfs.cpp

@ -15,7 +15,6 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -23,67 +22,104 @@
#include "fs.hpp" #include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
using std::size_t; using std::size_t;
using mergerfs::Policy;
using mergerfs::Category; using mergerfs::Category;
static static
void
_calc_mfs(const struct statvfs &st,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &mfs,
const string *&mfsbasepath)
int
_epmfs_create(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
fsblkcnt_t spaceavail;
string fullpath;
size_t epmfs;
const string *epmfsbasepath;
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail > mfs))
epmfs = 0;
epmfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
mfs = spaceavail;
mfsbasepath = basepath;
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath);
if(!fs::exists(fullpath))
continue;
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(spaceavail < epmfs)
continue;
epmfs = spaceavail;
epmfsbasepath = basepath;
} }
if(epmfsbasepath == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(epmfsbasepath);
return POLICY_SUCCESS;
} }
static static
int int
_epmfs(const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths)
_epmfs_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
string fullpath; string fullpath;
struct statvfs st;
fsblkcnt_t epmfs;
size_t epmfs;
const string *epmfsbasepath; const string *epmfsbasepath;
epmfs = 0; epmfs = 0;
epmfsbasepath = NULL; epmfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
size_t spaceavail;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
if(!fs::available(fullpath,needswritablefs,st))
if(!fs::exists(fullpath))
continue;
if(!fs::spaceavail(*basepath,spaceavail))
continue;
if(spaceavail < epmfs)
continue; continue;
_calc_mfs(st,basepath,minfreespace,epmfs,epmfsbasepath);
epmfs = spaceavail;
epmfsbasepath = basepath;
} }
if(epmfsbasepath == NULL) if(epmfsbasepath == NULL)
return (errno=ENOENT,POLICY_FAIL);
return POLICY_FAIL_ENOENT;
paths.push_back(epmfsbasepath); paths.push_back(epmfsbasepath);
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
static
int
_epmfs(const Category::Enum::Type type,
const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{
if(type == Category::Enum::create)
return _epmfs_create(basepaths,fusepath,paths);
return _epmfs_other(basepaths,fusepath,paths);
}
namespace mergerfs namespace mergerfs
{ {
int int
@ -94,12 +130,8 @@ namespace mergerfs
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv; int rv;
const size_t minfs =
((type == Category::Enum::create) ? minfreespace : 0);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _epmfs(basepaths,fusepath,minfs,needswritablefs,paths);
rv = _epmfs(type,basepaths,fusepath,paths);
if(POLICY_FAILED(rv)) if(POLICY_FAILED(rv))
rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);

2
src/policy_erofs.cpp

@ -33,6 +33,6 @@ namespace mergerfs
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
return (errno=EROFS,POLICY_FAIL);
return POLICY_FAIL_ERRNO(EROFS);
} }
} }

59
src/policy_ff.cpp

@ -29,19 +29,26 @@ using std::size_t;
static static
int int
_ff(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
_ff_create(const vector<string> &basepaths,
const size_t minfreespace,
vector<const string*> &paths)
{ {
string fullpath;
const string *fallback;
fallback = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath);
if(!fs::exists(fullpath))
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(fallback == NULL)
fallback = basepath;
if(spaceavail < minfreespace)
continue; continue;
paths.push_back(basepath); paths.push_back(basepath);
@ -49,34 +56,29 @@ _ff(const vector<string> &basepaths,
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
return POLICY_FAIL_ENOENT;
if(fallback == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(fallback);
return POLICY_SUCCESS;
} }
static static
int int
_ff_create(const vector<string> &basepaths,
const size_t minfreespace,
vector<const string*> &paths)
_ff_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
bool readonly;
size_t spaceavail;
const string *fallback;
string fullpath;
fallback = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
if(!fs::exists(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(fallback == NULL)
fallback = basepath;
fs::path::make(basepath,fusepath,fullpath);
if(spaceavail < minfreespace)
if(!fs::exists(fullpath))
continue; continue;
paths.push_back(basepath); paths.push_back(basepath);
@ -84,12 +86,7 @@ _ff_create(const vector<string> &basepaths,
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
if(fallback == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(fallback);
return POLICY_SUCCESS;
return POLICY_FAIL_ENOENT;
} }
namespace mergerfs namespace mergerfs
@ -104,6 +101,6 @@ namespace mergerfs
if(type == Category::Enum::create) if(type == Category::Enum::create)
return _ff_create(basepaths,minfreespace,paths); return _ff_create(basepaths,minfreespace,paths);
return _ff(basepaths,fusepath,paths);
return _ff_other(basepaths,fusepath,paths);
} }
} }

2
src/policy_invalid.cpp

@ -34,6 +34,6 @@ namespace mergerfs
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
return (errno=EINVAL,POLICY_FAIL);
return POLICY_FAIL_ERRNO(EINVAL);
} }
} }

91
src/policy_lfs.cpp

@ -15,75 +15,112 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp" #include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
using std::size_t; using std::size_t;
using mergerfs::Policy;
using mergerfs::Category; using mergerfs::Category;
static static
void
_calc_lfs(const struct statvfs &st,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &lfs,
const string *&lfsbasepath)
int
_lfs_create(const vector<string> &basepaths,
const size_t minfreespace,
vector<const string*> &paths)
{ {
fsblkcnt_t spaceavail;
string fullpath;
size_t lfs;
const string *lfsbasepath;
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail < lfs))
lfs = std::numeric_limits<size_t>::max();
lfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
lfs = spaceavail;
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i];
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(spaceavail < minfreespace)
continue;
if(spaceavail > lfs)
continue;
lfs = spaceavail;
lfsbasepath = basepath; lfsbasepath = basepath;
} }
if(lfsbasepath == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(lfsbasepath);
return POLICY_SUCCESS;
} }
static static
int int
_lfs(const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths)
_lfs_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
string fullpath; string fullpath;
struct statvfs st;
fsblkcnt_t lfs;
size_t lfs;
const string *lfsbasepath; const string *lfsbasepath;
lfs = -1;
lfs = std::numeric_limits<size_t>::max();
lfsbasepath = NULL; lfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
size_t spaceavail;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
if(!fs::available(fullpath,needswritablefs,st))
if(!fs::exists(fullpath))
continue;
if(!fs::spaceavail(*basepath,spaceavail))
continue;
if(spaceavail > lfs)
continue; continue;
_calc_lfs(st,basepath,minfreespace,lfs,lfsbasepath);
lfs = spaceavail;
lfsbasepath = basepath;
} }
if(lfsbasepath == NULL) if(lfsbasepath == NULL)
return (errno=ENOENT,POLICY_FAIL);
return POLICY_FAIL_ENOENT;
paths.push_back(lfsbasepath); paths.push_back(lfsbasepath);
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
static
int
_lfs(const Category::Enum::Type type,
const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
vector<const string*> &paths)
{
if(type == Category::Enum::create)
return _lfs_create(basepaths,minfreespace,paths);
return _lfs_other(basepaths,fusepath,paths);
}
namespace mergerfs namespace mergerfs
{ {
int int
@ -94,12 +131,8 @@ namespace mergerfs
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv; int rv;
const char *fp =
((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _lfs(basepaths,fp,minfreespace,needswritablefs,paths);
rv = _lfs(type,basepaths,fusepath,minfreespace,paths);
if(POLICY_FAILED(rv)) if(POLICY_FAILED(rv))
rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);

81
src/policy_mfs.cpp

@ -15,7 +15,6 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -23,63 +22,99 @@
#include "fs.hpp" #include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
using std::size_t; using std::size_t;
using mergerfs::Category;
static static
void
_calc_mfs(const struct statvfs &st,
const string *basepath,
fsblkcnt_t &mfs,
const string *&mfsbasepath)
int
_mfs_create(const vector<string> &basepaths,
vector<const string*> &paths)
{ {
fsblkcnt_t spaceavail;
string fullpath;
size_t mfs;
const string *mfsbasepath;
spaceavail = StatVFS::spaceavail(st);
if(spaceavail > mfs)
mfs = 0;
mfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
mfs = spaceavail;
bool readonly;
size_t spaceavail;
const string *basepath = &basepaths[i];
if(!fs::info(*basepath,readonly,spaceavail))
continue;
if(readonly)
continue;
if(spaceavail < mfs)
continue;
mfs = spaceavail;
mfsbasepath = basepath; mfsbasepath = basepath;
} }
if(mfsbasepath == NULL)
return POLICY_FAIL_ENOENT;
paths.push_back(mfsbasepath);
return POLICY_SUCCESS;
} }
static static
int int
_mfs(const vector<string> &basepaths,
const char *fusepath,
const bool needswritablefs,
vector<const string*> &paths)
_mfs_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
string fullpath; string fullpath;
struct statvfs st;
fsblkcnt_t mfs;
size_t mfs;
const string *mfsbasepath; const string *mfsbasepath;
mfs = 0; mfs = 0;
mfsbasepath = NULL; mfsbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
size_t spaceavail;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
if(!fs::available(fullpath,needswritablefs,st))
if(!fs::exists(fullpath))
continue;
if(!fs::spaceavail(*basepath,spaceavail))
continue;
if(spaceavail < mfs)
continue; continue;
_calc_mfs(st,basepath,mfs,mfsbasepath);
mfs = spaceavail;
mfsbasepath = basepath;
} }
if(mfsbasepath == NULL) if(mfsbasepath == NULL)
return (errno=ENOENT,POLICY_FAIL);
return POLICY_FAIL_ENOENT;
paths.push_back(mfsbasepath); paths.push_back(mfsbasepath);
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
static
int
_mfs(const Category::Enum::Type type,
const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{
if(type == Category::Enum::create)
return _mfs_create(basepaths,paths);
return _mfs_other(basepaths,fusepath,paths);
}
namespace mergerfs namespace mergerfs
{ {
int int
@ -90,12 +125,8 @@ namespace mergerfs
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv; int rv;
const char *fp =
((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _mfs(basepaths,fp,needswritablefs,paths);
rv = _mfs(type,basepaths,fusepath,paths);
if(POLICY_FAILED(rv)) if(POLICY_FAILED(rv))
rv = Policy::Func::ff(type,basepaths,fusepath,minfreespace,paths); rv = Policy::Func::ff(type,basepaths,fusepath,minfreespace,paths);

19
src/policy_newest.cpp

@ -38,13 +38,14 @@ _newest_create(const vector<string> &basepaths,
{ {
time_t newest; time_t newest;
string fullpath; string fullpath;
struct stat st;
const string *newestbasepath; const string *newestbasepath;
newest = std::numeric_limits<time_t>::min(); newest = std::numeric_limits<time_t>::min();
newestbasepath = NULL; newestbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
struct stat st;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
@ -53,10 +54,10 @@ _newest_create(const vector<string> &basepaths,
continue; continue;
if(st.st_mtime < newest) if(st.st_mtime < newest)
continue; continue;
if(!fs::exists_on_rw_fs(fullpath))
if(fs::readonly(*basepath))
continue; continue;
newest = st.st_mtime;
newest = st.st_mtime;
newestbasepath = basepath; newestbasepath = basepath;
} }
@ -70,19 +71,19 @@ _newest_create(const vector<string> &basepaths,
static static
int int
_newest(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
_newest_other(const vector<string> &basepaths,
const char *fusepath,
vector<const string*> &paths)
{ {
time_t newest; time_t newest;
string fullpath; string fullpath;
struct stat st;
const string *newestbasepath; const string *newestbasepath;
newest = std::numeric_limits<time_t>::min(); newest = std::numeric_limits<time_t>::min();
newestbasepath = NULL; newestbasepath = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
struct stat st;
const string *basepath = &basepaths[i]; const string *basepath = &basepaths[i];
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
@ -92,7 +93,7 @@ _newest(const vector<string> &basepaths,
if(st.st_mtime < newest) if(st.st_mtime < newest)
continue; continue;
newest = st.st_mtime;
newest = st.st_mtime;
newestbasepath = basepath; newestbasepath = basepath;
} }
@ -116,6 +117,6 @@ namespace mergerfs
if(type == Category::Enum::create) if(type == Category::Enum::create)
return _newest_create(basepaths,fusepath,paths); return _newest_create(basepaths,fusepath,paths);
return _newest(basepaths,fusepath,paths);
return _newest_other(basepaths,fusepath,paths);
} }
} }
Loading…
Cancel
Save