Browse Source

Merge pull request #242 from trapexit/statvfs

clearly separate usage of statvfs from stat for file existance
pull/243/head
Antonio SJ Musumeci 9 years ago
parent
commit
6d049c16d1
  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