Browse Source

Merge pull request #226 from trapexit/readonly

ignore drives mounted as readonly from create policies. closes #224
pull/227/head
Antonio SJ Musumeci 9 years ago
parent
commit
1bbe3a8879
  1. 83
      src/fs.cpp
  2. 17
      src/fs.hpp
  3. 19
      src/policy_all.cpp
  4. 45
      src/policy_eplfs.cpp
  5. 34
      src/policy_epmfs.cpp
  6. 32
      src/policy_ff.cpp
  7. 4
      src/policy_ffwp.cpp
  8. 29
      src/policy_fwfs.cpp
  9. 27
      src/policy_lfs.cpp
  10. 29
      src/policy_mfs.cpp
  11. 32
      src/policy_newest.cpp
  12. 55
      src/statvfs_util.hpp

83
src/fs.cpp

@ -31,28 +31,76 @@
#include "fs_attr.hpp" #include "fs_attr.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "fs_xattr.hpp" #include "fs_xattr.hpp"
#include "statvfs_util.hpp"
#include "str.hpp" #include "str.hpp"
#include "success_fail.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
namespace fs namespace fs
{ {
bool
exists(const string &path,
struct stat &st)
{
int rv;
rv = ::lstat(path.c_str(),&st);
return LSTAT_SUCCEEDED(rv);
}
bool
exists(const string &path,
struct statvfs &st)
{
int rv;
rv = ::statvfs(path.c_str(),&st);
return STATVFS_SUCCEEDED(rv);
}
bool
exists(const string &path)
{
struct stat st;
return exists(path,st);
}
bool
exists_on_rw_fs(const string &path,
struct statvfs &st)
{
int rv;
rv = ::statvfs(path.c_str(),&st);
return (STATVFS_SUCCEEDED(rv) && !StatVFS::readonly(st));
}
bool
exists_on_rw_fs(const string &path)
{
struct statvfs st;
return exists_on_rw_fs(path,st);
}
void void
findallfiles(const vector<string> &srcmounts, findallfiles(const vector<string> &srcmounts,
const char *fusepath, const char *fusepath,
vector<string> &paths) vector<string> &paths)
{ {
int rv;
string fullpath; string fullpath;
struct stat st;
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
{ {
fs::path::make(&srcmounts[i],fusepath,fullpath); fs::path::make(&srcmounts[i],fusepath,fullpath);
rv = ::lstat(fullpath.c_str(),&st);
if(rv == 0)
if(fs::exists(fullpath))
paths.push_back(fullpath); paths.push_back(fullpath);
} }
} }
@ -145,16 +193,14 @@ namespace fs
mfsidx = -1; mfsidx = -1;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
int rv;
struct statvfs fsstats;
struct statvfs st;
const string &basepath = basepaths[i]; const string &basepath = basepaths[i];
rv = ::statvfs(basepath.c_str(),&fsstats);
if(rv == 0)
if(fs::exists(basepath,st))
{ {
fsblkcnt_t spaceavail; fsblkcnt_t spaceavail;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > mfs) && (spaceavail >= minfreespace)) if((spaceavail > mfs) && (spaceavail >= minfreespace))
{ {
mfs = spaceavail; mfs = spaceavail;
@ -170,4 +216,23 @@ 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));
}
}; };

17
src/fs.hpp

@ -26,6 +26,16 @@ namespace fs
using std::string; using std::string;
using std::vector; using std::vector;
bool exists(const string &path,
struct stat &st);
bool exists(const string &path,
struct statvfs &st);
bool exists(const string &path);
bool exists_on_rw_fs(const string &path,
struct statvfs &st);
bool exists_on_rw_fs(const string &path);
void findallfiles(const vector<string> &srcmounts, void findallfiles(const vector<string> &srcmounts,
const char *fusepath, const char *fusepath,
vector<string> &paths); vector<string> &paths);
@ -45,6 +55,13 @@ 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__

19
src/policy_all.cpp

@ -14,17 +14,14 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -34,10 +31,9 @@ static
int int
_all(const vector<string> &basepaths, _all(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
struct stat st;
string fullpath; string fullpath;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
@ -46,9 +42,10 @@ _all(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::lstat(fullpath.c_str(),&st);
if(LSTAT_SUCCEEDED(rv))
paths.push_back(basepath);
if(!fs::available(fullpath,needswritablefs))
continue;
paths.push_back(basepath);
} }
if(paths.empty()) if(paths.empty())
@ -68,7 +65,9 @@ namespace mergerfs
{ {
const char *fp = const char *fp =
((type == Category::Enum::create) ? "" : fusepath); ((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
return _all(basepaths,fp,paths);
return _all(basepaths,fp,needswritablefs,paths);
} }
} }

45
src/policy_eplfs.cpp

@ -15,36 +15,33 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.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::Policy;
using mergerfs::Category; using mergerfs::Category;
typedef struct statvfs statvfs_t;
static static
void void
_calc_lfs(const statvfs_t &fsstats,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &lfs,
const string *&lfsbasepath)
_calc_lfs(const struct statvfs &st,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &lfs,
const string *&lfsbasepath)
{ {
fsblkcnt_t spaceavail; fsblkcnt_t spaceavail;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail < lfs)) if((spaceavail > minfreespace) && (spaceavail < lfs))
{ {
lfs = spaceavail; lfs = spaceavail;
@ -54,15 +51,14 @@ _calc_lfs(const statvfs_t &fsstats,
static static
int int
_eplfs(const Category::Enum::Type type,
const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
vector<const string*> &paths)
_eplfs(const vector<string> &basepaths,
const char *fusepath,
const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
statvfs_t fsstats;
struct statvfs st;
fsblkcnt_t eplfs; fsblkcnt_t eplfs;
const string *eplfsbasepath; const string *eplfsbasepath;
@ -74,9 +70,10 @@ _eplfs(const Category::Enum::Type type,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::statvfs(fullpath.c_str(),&fsstats);
if(STATVFS_SUCCEEDED(rv))
_calc_lfs(fsstats,basepath,minfreespace,eplfs,eplfsbasepath);
if(!fs::available(fullpath,needswritablefs,st))
continue;
_calc_lfs(st,basepath,minfreespace,eplfs,eplfsbasepath);
} }
if(eplfsbasepath == NULL) if(eplfsbasepath == NULL)
@ -94,13 +91,15 @@ namespace mergerfs
const vector<string> &basepaths, 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)
{ {
int rv; int rv;
const bool needswritablefs =
(type == Category::Enum::create);
const size_t minfs = const size_t minfs =
((type == Category::Enum::create) ? minfreespace : 0); ((type == Category::Enum::create) ? minfreespace : 0);
rv = _eplfs(type,basepaths,fusepath,minfs,paths);
rv = _eplfs(basepaths,fusepath,minfs,needswritablefs,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);

34
src/policy_epmfs.cpp

@ -15,36 +15,33 @@
*/ */
#include <errno.h> #include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.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::Policy;
using mergerfs::Category; using mergerfs::Category;
typedef struct statvfs statvfs_t;
static static
void void
_calc_mfs(const statvfs_t &fsstats,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &mfs,
const string *&mfsbasepath)
_calc_mfs(const struct statvfs &st,
const string *basepath,
const size_t minfreespace,
fsblkcnt_t &mfs,
const string *&mfsbasepath)
{ {
fsblkcnt_t spaceavail; fsblkcnt_t spaceavail;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail > mfs)) if((spaceavail > minfreespace) && (spaceavail > mfs))
{ {
mfs = spaceavail; mfs = spaceavail;
@ -57,11 +54,11 @@ int
_epmfs(const vector<string> &basepaths, _epmfs(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const size_t minfreespace, const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
statvfs_t fsstats;
struct statvfs st;
fsblkcnt_t epmfs; fsblkcnt_t epmfs;
const string *epmfsbasepath; const string *epmfsbasepath;
@ -73,9 +70,10 @@ _epmfs(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::statvfs(fullpath.c_str(),&fsstats);
if(STATVFS_SUCCEEDED(rv))
_calc_mfs(fsstats,basepath,minfreespace,epmfs,epmfsbasepath);
if(!fs::available(fullpath,needswritablefs,st))
continue;
_calc_mfs(st,basepath,minfreespace,epmfs,epmfsbasepath);
} }
if(epmfsbasepath == NULL) if(epmfsbasepath == NULL)
@ -98,8 +96,10 @@ namespace mergerfs
int rv; int rv;
const size_t minfs = const size_t minfs =
((type == Category::Enum::create) ? minfreespace : 0); ((type == Category::Enum::create) ? minfreespace : 0);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _epmfs(basepaths,fusepath,minfs,paths);
rv = _epmfs(basepaths,fusepath,minfs,needswritablefs,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);

32
src/policy_ff.cpp

@ -14,17 +14,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -34,11 +33,12 @@ static
int int
_ff(const vector<string> &basepaths, _ff(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
struct stat st;
struct statvfs st;
const string *fallback = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
@ -46,15 +46,27 @@ _ff(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::lstat(fullpath.c_str(),&st);
if(LSTAT_FAILED(rv))
if(!fs::exists(fullpath,st))
continue; continue;
if(needswritablefs && StatVFS::readonly(st))
{
if(fallback == NULL)
fallback = basepath;
continue;
}
paths.push_back(basepath); paths.push_back(basepath);
return POLICY_SUCCESS; return POLICY_SUCCESS;
} }
if(fallback != NULL)
{
paths.push_back(fallback);
return POLICY_SUCCESS;
}
return (errno=ENOENT,POLICY_FAIL); return (errno=ENOENT,POLICY_FAIL);
} }
@ -69,7 +81,9 @@ namespace mergerfs
{ {
const char *fp = const char *fp =
((type == Category::Enum::create) ? "" : fusepath); ((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
return _ff(basepaths,fp,paths);
return _ff(basepaths,fp,needswritablefs,paths);
} }
} }

4
src/policy_ffwp.cpp

@ -14,10 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h>
#include <string> #include <string>
#include <vector> #include <vector>

29
src/policy_fwfs.cpp

@ -14,15 +14,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/statvfs.h>
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -35,11 +36,11 @@ int
_fwfs(const vector<string> &basepaths, _fwfs(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const size_t minfreespace, const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
struct statvfs fsstats;
struct statvfs st;
for(size_t i = 0, size = basepaths.size(); i != size; i++) for(size_t i = 0, size = basepaths.size(); i != size; i++)
{ {
@ -47,19 +48,15 @@ _fwfs(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::statvfs(fullpath.c_str(),&fsstats);
if(STATVFS_SUCCEEDED(rv))
{
fsblkcnt_t spaceavail;
if(!fs::available(fullpath,needswritablefs,st))
continue;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
if(spaceavail < minfreespace)
continue;
if(StatVFS::spaceavail(st) < minfreespace)
continue;
paths.push_back(basepath);
paths.push_back(basepath);
return POLICY_SUCCESS;
}
return POLICY_SUCCESS;
} }
return (errno=ENOENT,POLICY_FAIL); return (errno=ENOENT,POLICY_FAIL);
@ -77,8 +74,10 @@ namespace mergerfs
int rv; int rv;
const char *fp = const char *fp =
((type == Category::Enum::create) ? "" : fusepath); ((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _fwfs(basepaths,fp,minfreespace,paths);
rv = _fwfs(basepaths,fp,minfreespace,needswritablefs,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);

27
src/policy_lfs.cpp

@ -14,18 +14,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -35,7 +33,7 @@ using mergerfs::Category;
static static
void void
_calc_lfs(const struct statvfs &fsstats,
_calc_lfs(const struct statvfs &st,
const string *basepath, const string *basepath,
const size_t minfreespace, const size_t minfreespace,
fsblkcnt_t &lfs, fsblkcnt_t &lfs,
@ -43,7 +41,7 @@ _calc_lfs(const struct statvfs &fsstats,
{ {
fsblkcnt_t spaceavail; fsblkcnt_t spaceavail;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
spaceavail = StatVFS::spaceavail(st);
if((spaceavail > minfreespace) && (spaceavail < lfs)) if((spaceavail > minfreespace) && (spaceavail < lfs))
{ {
lfs = spaceavail; lfs = spaceavail;
@ -56,11 +54,11 @@ int
_lfs(const vector<string> &basepaths, _lfs(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const size_t minfreespace, const size_t minfreespace,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
struct statvfs fsstats;
struct statvfs st;
fsblkcnt_t lfs; fsblkcnt_t lfs;
const string *lfsbasepath; const string *lfsbasepath;
@ -72,9 +70,10 @@ _lfs(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::statvfs(fullpath.c_str(),&fsstats);
if(STATVFS_SUCCEEDED(rv))
_calc_lfs(fsstats,basepath,minfreespace,lfs,lfsbasepath);
if(!fs::available(fullpath,needswritablefs,st))
continue;
_calc_lfs(st,basepath,minfreespace,lfs,lfsbasepath);
} }
if(lfsbasepath == NULL) if(lfsbasepath == NULL)
@ -97,8 +96,10 @@ namespace mergerfs
int rv; int rv;
const char *fp = const char *fp =
((type == Category::Enum::create) ? "" : fusepath); ((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _lfs(basepaths,fp,minfreespace,paths);
rv = _lfs(basepaths,fp,minfreespace,needswritablefs,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);

29
src/policy_mfs.cpp

@ -14,15 +14,16 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/statvfs.h>
#include <errno.h> #include <errno.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "fs.hpp"
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -30,14 +31,14 @@ using std::size_t;
static static
void void
_calc_mfs(const struct statvfs &fsstats,
_calc_mfs(const struct statvfs &st,
const string *basepath, const string *basepath,
fsblkcnt_t &mfs, fsblkcnt_t &mfs,
const string *&mfsbasepath) const string *&mfsbasepath)
{ {
fsblkcnt_t spaceavail; fsblkcnt_t spaceavail;
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
spaceavail = StatVFS::spaceavail(st);
if(spaceavail > mfs) if(spaceavail > mfs)
{ {
mfs = spaceavail; mfs = spaceavail;
@ -49,11 +50,11 @@ static
int int
_mfs(const vector<string> &basepaths, _mfs(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
string fullpath; string fullpath;
struct statvfs fsstats;
struct statvfs st;
fsblkcnt_t mfs; fsblkcnt_t mfs;
const string *mfsbasepath; const string *mfsbasepath;
@ -65,9 +66,10 @@ _mfs(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::statvfs(fullpath.c_str(),&fsstats);
if(STATVFS_SUCCEEDED(rv))
_calc_mfs(fsstats,basepath,mfs,mfsbasepath);
if(!fs::available(fullpath,needswritablefs,st))
continue;
_calc_mfs(st,basepath,mfs,mfsbasepath);
} }
if(mfsbasepath == NULL) if(mfsbasepath == NULL)
@ -87,9 +89,16 @@ namespace mergerfs
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
const char *fp = const char *fp =
((type == Category::Enum::create) ? "" : fusepath); ((type == Category::Enum::create) ? "" : fusepath);
const bool needswritablefs =
(type == Category::Enum::create);
rv = _mfs(basepaths,fp,needswritablefs,paths);
if(POLICY_FAILED(rv))
rv = Policy::Func::ff(type,basepaths,fusepath,minfreespace,paths);
return _mfs(basepaths,fp,paths);
return rv;
} }
} }

32
src/policy_newest.cpp

@ -14,10 +14,9 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -26,6 +25,7 @@
#include "fs_path.hpp" #include "fs_path.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "success_fail.hpp" #include "success_fail.hpp"
#include "statvfs_util.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
@ -35,12 +35,12 @@ static
int int
_newest(const vector<string> &basepaths, _newest(const vector<string> &basepaths,
const char *fusepath, const char *fusepath,
const bool needswritablefs,
vector<const string*> &paths) vector<const string*> &paths)
{ {
int rv;
struct stat st;
string fullpath;
time_t newest; time_t newest;
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();
@ -51,12 +51,15 @@ _newest(const vector<string> &basepaths,
fs::path::make(basepath,fusepath,fullpath); fs::path::make(basepath,fusepath,fullpath);
rv = ::lstat(fullpath.c_str(),&st);
if(LSTAT_SUCCEEDED(rv) && (st.st_mtime >= newest))
{
newest = st.st_mtime;
newestbasepath = basepath;
}
if(!fs::exists(fullpath,st))
continue;
if(st.st_mtime < newest)
continue;
if(needswritablefs && !fs::exists_on_rw_fs(fullpath))
continue;
newest = st.st_mtime;
newestbasepath = basepath;
} }
if(newestbasepath == NULL) if(newestbasepath == NULL)
@ -76,6 +79,9 @@ namespace mergerfs
const size_t minfreespace, const size_t minfreespace,
vector<const string*> &paths) vector<const string*> &paths)
{ {
return _newest(basepaths,fusepath,paths);
const bool needswritablefs =
(type == Category::Enum::create);
return _newest(basepaths,fusepath,needswritablefs,paths);
} }
} }

55
src/statvfs_util.hpp

@ -0,0 +1,55 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/statvfs.h>
#include <string>
#include "success_fail.hpp"
namespace StatVFS
{
static
inline
bool
readonly(const struct statvfs &st)
{
return (st.f_flag & ST_RDONLY);
}
static
inline
bool
readonly(const std::string &path)
{
int rv;
struct statvfs st;
rv = ::statvfs(path.c_str(),&st);
if(STATVFS_FAILED(rv))
return false;
return readonly(st);
}
static
inline
fsblkcnt_t
spaceavail(const struct statvfs &st)
{
return (st.f_frsize * st.f_bavail);
}
}
Loading…
Cancel
Save