mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-01-20 02:32:45 +08:00
Merge pull request #242 from trapexit/statvfs
clearly separate usage of statvfs from stat for file existance
This commit is contained in:
commit
6d049c16d1
82
src/fs.cpp
82
src/fs.cpp
|
@ -52,8 +52,16 @@ namespace fs
|
|||
}
|
||||
|
||||
bool
|
||||
exists(const string &path,
|
||||
struct statvfs &st)
|
||||
exists(const string &path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
return exists(path,st);
|
||||
}
|
||||
|
||||
bool
|
||||
statvfs(const string &path,
|
||||
struct statvfs &st)
|
||||
{
|
||||
int rv;
|
||||
|
||||
|
@ -63,22 +71,14 @@ namespace fs
|
|||
}
|
||||
|
||||
bool
|
||||
exists(const string &path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
return exists(path,st);
|
||||
}
|
||||
|
||||
bool
|
||||
exists(const string &path,
|
||||
bool &readonly,
|
||||
size_t &spaceavail)
|
||||
info(const string &path,
|
||||
bool &readonly,
|
||||
size_t &spaceavail)
|
||||
{
|
||||
bool rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = exists(path,st);
|
||||
rv = fs::statvfs(path,st);
|
||||
if(rv)
|
||||
{
|
||||
readonly = StatVFS::readonly(st);
|
||||
|
@ -89,33 +89,28 @@ namespace fs
|
|||
}
|
||||
|
||||
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
|
||||
exists_on_rw_fs(const string &path)
|
||||
spaceavail(const string &path,
|
||||
size_t &spaceavail)
|
||||
{
|
||||
bool rv;
|
||||
struct statvfs st;
|
||||
|
||||
return exists_on_rw_fs(path,st);
|
||||
}
|
||||
rv = fs::statvfs(path,st);
|
||||
if(rv)
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
|
||||
bool
|
||||
exists_on_rw_fs_with_at_least(const string &path,
|
||||
const size_t minfreespace)
|
||||
{
|
||||
struct statvfs st;
|
||||
|
||||
return (exists_on_rw_fs(path,st)
|
||||
&&
|
||||
StatVFS::spaceavail(st) >= minfreespace);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -224,20 +219,18 @@ namespace fs
|
|||
string &path)
|
||||
{
|
||||
fsblkcnt_t mfs;
|
||||
fsblkcnt_t spaceavail;
|
||||
const string *mfsbasepath;
|
||||
|
||||
mfs = 0;
|
||||
mfsbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
struct statvfs st;
|
||||
size_t spaceavail;
|
||||
const string &basepath = basepaths[i];
|
||||
|
||||
if(!fs::exists(basepath,st))
|
||||
if(!fs::spaceavail(basepath,spaceavail))
|
||||
continue;
|
||||
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
if(spaceavail < minfreespace)
|
||||
continue;
|
||||
if(spaceavail <= mfs)
|
||||
|
@ -254,23 +247,4 @@ namespace fs
|
|||
|
||||
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
27
src/fs.hpp
|
@ -28,19 +28,19 @@ namespace fs
|
|||
|
||||
bool exists(const string &path,
|
||||
struct stat &st);
|
||||
bool exists(const string &path,
|
||||
struct statvfs &st);
|
||||
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 exists_on_rw_fs_with_at_least(const string &path,
|
||||
const size_t minfreespace);
|
||||
bool info(const string &path,
|
||||
bool &readonly,
|
||||
size_t &spaceavail);
|
||||
|
||||
bool readonly(const string &path);
|
||||
|
||||
bool spaceavail(const string &path,
|
||||
size_t &spaceavail);
|
||||
|
||||
void findallfiles(const vector<string> &srcmounts,
|
||||
const char *fusepath,
|
||||
|
@ -61,13 +61,6 @@ namespace fs
|
|||
int mfs(const vector<string> &srcs,
|
||||
const size_t minfreespace,
|
||||
string &path);
|
||||
|
||||
bool available(const string &path,
|
||||
const bool needswritablefs);
|
||||
|
||||
bool available(const string &path,
|
||||
const bool needswritablefs,
|
||||
struct statvfs &st);
|
||||
};
|
||||
|
||||
#endif // __FS_HPP__
|
||||
|
|
|
@ -29,15 +29,21 @@ using std::size_t;
|
|||
|
||||
static
|
||||
int
|
||||
_all_create(const vector<string> &srcmounts,
|
||||
_all_create(const vector<string> &basepaths,
|
||||
const size_t minfreespace,
|
||||
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;
|
||||
|
||||
paths.push_back(basepath);
|
||||
|
@ -51,15 +57,15 @@ _all_create(const vector<string> &srcmounts,
|
|||
|
||||
static
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -79,14 +85,14 @@ namespace mergerfs
|
|||
{
|
||||
int
|
||||
Policy::Func::all(const Category::Enum::Type type,
|
||||
const vector<string> &srcmounts,
|
||||
const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
const size_t minfreespace,
|
||||
fsblkcnt_t &lfs,
|
||||
const string *&lfsbasepath)
|
||||
{
|
||||
fsblkcnt_t spaceavail;
|
||||
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
if((spaceavail > minfreespace) && (spaceavail < lfs))
|
||||
{
|
||||
lfs = spaceavail;
|
||||
lfsbasepath = basepath;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_eplfs(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const size_t minfreespace,
|
||||
const bool needswritablefs,
|
||||
vector<const string*> &paths)
|
||||
_eplfs_create(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const size_t minfreespace,
|
||||
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++)
|
||||
{
|
||||
bool readonly;
|
||||
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::info(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
if(readonly)
|
||||
continue;
|
||||
if(spaceavail < minfreespace)
|
||||
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_other(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
size_t eplfs;
|
||||
const string *eplfsbasepath;
|
||||
|
||||
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::exists(fullpath))
|
||||
continue;
|
||||
if(!fs::spaceavail(*basepath,spaceavail))
|
||||
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 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);
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -23,67 +22,104 @@
|
|||
#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_mfs(const struct statvfs &st,
|
||||
const string *basepath,
|
||||
const size_t minfreespace,
|
||||
fsblkcnt_t &mfs,
|
||||
const string *&mfsbasepath)
|
||||
{
|
||||
fsblkcnt_t spaceavail;
|
||||
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
if((spaceavail > minfreespace) && (spaceavail > mfs))
|
||||
{
|
||||
mfs = spaceavail;
|
||||
mfsbasepath = basepath;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_epmfs(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const size_t minfreespace,
|
||||
const bool needswritablefs,
|
||||
vector<const string*> &paths)
|
||||
_epmfs_create(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
struct statvfs st;
|
||||
fsblkcnt_t epmfs;
|
||||
size_t epmfs;
|
||||
const string *epmfsbasepath;
|
||||
|
||||
epmfs = 0;
|
||||
epmfsbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
bool readonly;
|
||||
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::info(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
if(readonly)
|
||||
continue;
|
||||
if(spaceavail < epmfs)
|
||||
continue;
|
||||
|
||||
_calc_mfs(st,basepath,minfreespace,epmfs,epmfsbasepath);
|
||||
epmfs = spaceavail;
|
||||
epmfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(epmfsbasepath == NULL)
|
||||
return (errno=ENOENT,POLICY_FAIL);
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(epmfsbasepath);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_epmfs_other(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
size_t epmfs;
|
||||
const string *epmfsbasepath;
|
||||
|
||||
epmfs = 0;
|
||||
epmfsbasepath = 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::exists(fullpath))
|
||||
continue;
|
||||
if(!fs::spaceavail(*basepath,spaceavail))
|
||||
continue;
|
||||
if(spaceavail < epmfs)
|
||||
continue;
|
||||
|
||||
epmfs = spaceavail;
|
||||
epmfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(epmfsbasepath == NULL)
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(epmfsbasepath);
|
||||
|
||||
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
|
||||
{
|
||||
int
|
||||
|
@ -94,12 +130,8 @@ namespace mergerfs
|
|||
vector<const string*> &paths)
|
||||
{
|
||||
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))
|
||||
rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
||||
|
||||
|
|
|
@ -33,6 +33,6 @@ namespace mergerfs
|
|||
const size_t minfreespace,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
return (errno=EROFS,POLICY_FAIL);
|
||||
return POLICY_FAIL_ERRNO(EROFS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,46 @@ using std::size_t;
|
|||
|
||||
static
|
||||
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)
|
||||
{
|
||||
const string *fallback;
|
||||
|
||||
fallback = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
bool readonly;
|
||||
size_t spaceavail;
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
if(!fs::info(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
if(readonly)
|
||||
continue;
|
||||
if(fallback == NULL)
|
||||
fallback = basepath;
|
||||
if(spaceavail < minfreespace)
|
||||
continue;
|
||||
|
||||
paths.push_back(basepath);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
if(fallback == NULL)
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(fallback);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_ff_other(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
|
||||
|
@ -52,46 +89,6 @@ _ff(const vector<string> &basepaths,
|
|||
return POLICY_FAIL_ENOENT;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_ff_create(const vector<string> &basepaths,
|
||||
const size_t minfreespace,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
bool readonly;
|
||||
size_t spaceavail;
|
||||
const string *fallback;
|
||||
|
||||
fallback = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
if(!fs::exists(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
|
||||
if(readonly)
|
||||
continue;
|
||||
|
||||
if(fallback == NULL)
|
||||
fallback = basepath;
|
||||
|
||||
if(spaceavail < minfreespace)
|
||||
continue;
|
||||
|
||||
paths.push_back(basepath);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
if(fallback == NULL)
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(fallback);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
int
|
||||
|
@ -104,6 +101,6 @@ namespace mergerfs
|
|||
if(type == Category::Enum::create)
|
||||
return _ff_create(basepaths,minfreespace,paths);
|
||||
|
||||
return _ff(basepaths,fusepath,paths);
|
||||
return _ff_other(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,6 @@ namespace mergerfs
|
|||
const size_t minfreespace,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
return (errno=EINVAL,POLICY_FAIL);
|
||||
return POLICY_FAIL_ERRNO(EINVAL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,75 +15,112 @@
|
|||
*/
|
||||
|
||||
#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,
|
||||
const size_t minfreespace,
|
||||
fsblkcnt_t &lfs,
|
||||
const string *&lfsbasepath)
|
||||
{
|
||||
fsblkcnt_t spaceavail;
|
||||
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
if((spaceavail > minfreespace) && (spaceavail < lfs))
|
||||
{
|
||||
lfs = spaceavail;
|
||||
lfsbasepath = basepath;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_lfs(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const size_t minfreespace,
|
||||
const bool needswritablefs,
|
||||
vector<const string*> &paths)
|
||||
_lfs_create(const vector<string> &basepaths,
|
||||
const size_t minfreespace,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
struct statvfs st;
|
||||
fsblkcnt_t lfs;
|
||||
size_t lfs;
|
||||
const string *lfsbasepath;
|
||||
|
||||
lfs = -1;
|
||||
lfs = std::numeric_limits<size_t>::max();
|
||||
lfsbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
bool readonly;
|
||||
size_t spaceavail;
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
fs::path::make(basepath,fusepath,fullpath);
|
||||
|
||||
if(!fs::available(fullpath,needswritablefs,st))
|
||||
if(!fs::info(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
if(readonly)
|
||||
continue;
|
||||
if(spaceavail < minfreespace)
|
||||
continue;
|
||||
if(spaceavail > lfs)
|
||||
continue;
|
||||
|
||||
_calc_lfs(st,basepath,minfreespace,lfs,lfsbasepath);
|
||||
lfs = spaceavail;
|
||||
lfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(lfsbasepath == NULL)
|
||||
return (errno=ENOENT,POLICY_FAIL);
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(lfsbasepath);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_lfs_other(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
size_t lfs;
|
||||
const string *lfsbasepath;
|
||||
|
||||
lfs = std::numeric_limits<size_t>::max();
|
||||
lfsbasepath = 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::exists(fullpath))
|
||||
continue;
|
||||
if(!fs::spaceavail(*basepath,spaceavail))
|
||||
continue;
|
||||
if(spaceavail > lfs)
|
||||
continue;
|
||||
|
||||
lfs = spaceavail;
|
||||
lfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(lfsbasepath == NULL)
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(lfsbasepath);
|
||||
|
||||
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
|
||||
{
|
||||
int
|
||||
|
@ -94,12 +131,8 @@ namespace mergerfs
|
|||
vector<const string*> &paths)
|
||||
{
|
||||
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))
|
||||
rv = Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -23,63 +22,99 @@
|
|||
#include "fs.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "statvfs_util.hpp"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
void
|
||||
_calc_mfs(const struct statvfs &st,
|
||||
const string *basepath,
|
||||
fsblkcnt_t &mfs,
|
||||
const string *&mfsbasepath)
|
||||
{
|
||||
fsblkcnt_t spaceavail;
|
||||
|
||||
spaceavail = StatVFS::spaceavail(st);
|
||||
if(spaceavail > mfs)
|
||||
{
|
||||
mfs = spaceavail;
|
||||
mfsbasepath = basepath;
|
||||
}
|
||||
}
|
||||
using mergerfs::Category;
|
||||
|
||||
static
|
||||
int
|
||||
_mfs(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
const bool needswritablefs,
|
||||
vector<const string*> &paths)
|
||||
_mfs_create(const vector<string> &basepaths,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
struct statvfs st;
|
||||
fsblkcnt_t mfs;
|
||||
size_t mfs;
|
||||
const string *mfsbasepath;
|
||||
|
||||
mfs = 0;
|
||||
mfsbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
bool readonly;
|
||||
size_t spaceavail;
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
fs::path::make(basepath,fusepath,fullpath);
|
||||
|
||||
if(!fs::available(fullpath,needswritablefs,st))
|
||||
if(!fs::info(*basepath,readonly,spaceavail))
|
||||
continue;
|
||||
if(readonly)
|
||||
continue;
|
||||
if(spaceavail < mfs)
|
||||
continue;
|
||||
|
||||
_calc_mfs(st,basepath,mfs,mfsbasepath);
|
||||
mfs = spaceavail;
|
||||
mfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(mfsbasepath == NULL)
|
||||
return (errno=ENOENT,POLICY_FAIL);
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(mfsbasepath);
|
||||
|
||||
return POLICY_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_mfs_other(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<const string*> &paths)
|
||||
{
|
||||
string fullpath;
|
||||
size_t mfs;
|
||||
const string *mfsbasepath;
|
||||
|
||||
mfs = 0;
|
||||
mfsbasepath = 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::exists(fullpath))
|
||||
continue;
|
||||
if(!fs::spaceavail(*basepath,spaceavail))
|
||||
continue;
|
||||
if(spaceavail < mfs)
|
||||
continue;
|
||||
|
||||
mfs = spaceavail;
|
||||
mfsbasepath = basepath;
|
||||
}
|
||||
|
||||
if(mfsbasepath == NULL)
|
||||
return POLICY_FAIL_ENOENT;
|
||||
|
||||
paths.push_back(mfsbasepath);
|
||||
|
||||
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
|
||||
{
|
||||
int
|
||||
|
@ -90,12 +125,8 @@ namespace mergerfs
|
|||
vector<const string*> &paths)
|
||||
{
|
||||
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))
|
||||
rv = Policy::Func::ff(type,basepaths,fusepath,minfreespace,paths);
|
||||
|
||||
|
|
|
@ -38,13 +38,14 @@ _newest_create(const vector<string> &basepaths,
|
|||
{
|
||||
time_t newest;
|
||||
string fullpath;
|
||||
struct stat st;
|
||||
const string *newestbasepath;
|
||||
|
||||
newest = std::numeric_limits<time_t>::min();
|
||||
newestbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
|
||||
struct stat st;
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
fs::path::make(basepath,fusepath,fullpath);
|
||||
|
@ -53,10 +54,10 @@ _newest_create(const vector<string> &basepaths,
|
|||
continue;
|
||||
if(st.st_mtime < newest)
|
||||
continue;
|
||||
if(!fs::exists_on_rw_fs(fullpath))
|
||||
if(fs::readonly(*basepath))
|
||||
continue;
|
||||
|
||||
newest = st.st_mtime;
|
||||
newest = st.st_mtime;
|
||||
newestbasepath = basepath;
|
||||
}
|
||||
|
||||
|
@ -70,19 +71,19 @@ _newest_create(const vector<string> &basepaths,
|
|||
|
||||
static
|
||||
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;
|
||||
string fullpath;
|
||||
struct stat st;
|
||||
const string *newestbasepath;
|
||||
|
||||
newest = std::numeric_limits<time_t>::min();
|
||||
newestbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
struct stat st;
|
||||
const string *basepath = &basepaths[i];
|
||||
|
||||
fs::path::make(basepath,fusepath,fullpath);
|
||||
|
@ -92,7 +93,7 @@ _newest(const vector<string> &basepaths,
|
|||
if(st.st_mtime < newest)
|
||||
continue;
|
||||
|
||||
newest = st.st_mtime;
|
||||
newest = st.st_mtime;
|
||||
newestbasepath = basepath;
|
||||
}
|
||||
|
||||
|
@ -116,6 +117,6 @@ namespace mergerfs
|
|||
if(type == Category::Enum::create)
|
||||
return _newest_create(basepaths,fusepath,paths);
|
||||
|
||||
return _newest(basepaths,fusepath,paths);
|
||||
return _newest_other(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user