mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-01-20 07:12:46 +08:00
ignore drives mounted as readonly from create policies. closes #224
This commit is contained in:
parent
8edb7c1e1c
commit
5813d1e477
83
src/fs.cpp
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(fs::exists(fullpath))
|
||||||
if(rv == 0)
|
|
||||||
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 st;
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
const string &basepath = basepaths[i];
|
||||||
|
|
||||||
rv = ::statvfs(basepath.c_str(),&fsstats);
|
if(fs::exists(basepath,st))
|
||||||
if(rv == 0)
|
|
||||||
{
|
{
|
||||||
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
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__
|
||||||
|
|
|
@ -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(!fs::available(fullpath,needswritablefs))
|
||||||
if(LSTAT_SUCCEEDED(rv))
|
continue;
|
||||||
paths.push_back(basepath);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
_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,
|
||||||
const string *&lfsbasepath)
|
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,
|
_eplfs(const vector<string> &basepaths,
|
||||||
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 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(!fs::available(fullpath,needswritablefs,st))
|
||||||
if(STATVFS_SUCCEEDED(rv))
|
continue;
|
||||||
_calc_lfs(fsstats,basepath,minfreespace,eplfs,eplfsbasepath);
|
|
||||||
|
_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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
_calc_mfs(const struct statvfs &st,
|
||||||
const string *basepath,
|
const string *basepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
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 > 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(!fs::available(fullpath,needswritablefs,st))
|
||||||
if(STATVFS_SUCCEEDED(rv))
|
continue;
|
||||||
_calc_mfs(fsstats,basepath,minfreespace,epmfs,epmfsbasepath);
|
|
||||||
|
_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);
|
||||||
|
|
||||||
|
|
|
@ -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(!fs::exists(fullpath,st))
|
||||||
if(LSTAT_FAILED(rv))
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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(!fs::available(fullpath,needswritablefs,st))
|
||||||
if(STATVFS_SUCCEEDED(rv))
|
continue;
|
||||||
{
|
|
||||||
fsblkcnt_t spaceavail;
|
|
||||||
|
|
||||||
spaceavail = (fsstats.f_frsize * fsstats.f_bavail);
|
if(StatVFS::spaceavail(st) < minfreespace)
|
||||||
if(spaceavail < minfreespace)
|
continue;
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -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(!fs::available(fullpath,needswritablefs,st))
|
||||||
if(STATVFS_SUCCEEDED(rv))
|
continue;
|
||||||
_calc_lfs(fsstats,basepath,minfreespace,lfs,lfsbasepath);
|
|
||||||
|
_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);
|
||||||
|
|
||||||
|
|
|
@ -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(!fs::available(fullpath,needswritablefs,st))
|
||||||
if(STATVFS_SUCCEEDED(rv))
|
continue;
|
||||||
_calc_mfs(fsstats,basepath,mfs,mfsbasepath);
|
|
||||||
|
_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);
|
||||||
|
|
||||||
return _mfs(basepaths,fp,paths);
|
rv = _mfs(basepaths,fp,needswritablefs,paths);
|
||||||
|
if(POLICY_FAILED(rv))
|
||||||
|
rv = Policy::Func::ff(type,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(!fs::exists(fullpath,st))
|
||||||
if(LSTAT_SUCCEEDED(rv) && (st.st_mtime >= newest))
|
continue;
|
||||||
{
|
if(st.st_mtime < newest)
|
||||||
newest = st.st_mtime;
|
continue;
|
||||||
newestbasepath = basepath;
|
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
Normal file
55
src/statvfs_util.hpp
Normal file
|
@ -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…
Reference in New Issue
Block a user