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