mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-03-15 02:35:12 +08:00
Merge pull request #45 from trapexit/remove_all
Remove 'all' policy and simplify logic
This commit is contained in:
commit
58ec83dcd8
@ -47,7 +47,7 @@ In /etc/fstab it'd look like the following:
|
|||||||
|
|
||||||
# POLICIES
|
# POLICIES
|
||||||
|
|
||||||
Filesystem calls are broken up into 4 functional categories: search, action, create, and none. These categories can be assigned a policy which dictates how [mergerfs](http://github.com/trapexit/mergerfs) behaves while when action on the filesystem. Any policy can be assigned to a category though some aren't terribly practical. For instance: rand (Random) may be useful for **create** but could lead to very odd behavior if used for **search** or **action**. Since the input for any policy is the source mounts and fusepath and the output a vector of targets the choice was made to simplify the implementation and allow a policies usage in any category. **NOTE:** In any policy which can return more than one location (currently only **all**) the first value will be used in **search** and **create** policies since they can only ever act on 1 filepath.
|
Filesystem calls are broken up into 3 categories: search, action, and create. There are also some calls which have no policy attached due to state being kept between calls. These categories can be assigned a policy which dictates how [mergerfs](http://github.com/trapexit/mergerfs) behaves. Any policy can be assigned to a category though some aren't terribly practical. For instance: rand (Random) may be useful for **create** but could lead to very odd behavior if used for **search** or **action**.
|
||||||
|
|
||||||
#### Functional classifications ####
|
#### Functional classifications ####
|
||||||
| Class | FUSE calls |
|
| Class | FUSE calls |
|
||||||
@ -60,13 +60,12 @@ Filesystem calls are broken up into 4 functional categories: search, action, cre
|
|||||||
#### Policy descriptions ####
|
#### Policy descriptions ####
|
||||||
| Policy | Description |
|
| Policy | Description |
|
||||||
|--------------|-------------|
|
|--------------|-------------|
|
||||||
| ff (first found) | Given the order the paths were provided at mount time act on the first one found (regardless if stat would return EACCES). |
|
| ff (first found) | Given the order of the paths act on the first one found (regardless if stat would return EACCES). |
|
||||||
| ffwp (first found w/ permissions) | Given the order the paths were provided at mount time act on the first one found which you have access (stat does not error with EACCES). |
|
| ffwp (first found w/ permissions) | Given the order of the paths act on the first one found which you have access (stat does not error with EACCES). |
|
||||||
| newest (newest file) | If multiple files exist return the one with the most recent mtime. |
|
| newest (newest file) | If multiple files exist return the one with the most recent mtime. |
|
||||||
| all (all files found) | Attempt to apply the call to each file found. If any sub call succeeds the entire operation succeeds and other errors ignored. If all fail then the last error is reported. |
|
|
||||||
| mfs (most free space) | Assuming the path is found to exist (ENOENT would not be returned) use the drive with the most free space available. |
|
| mfs (most free space) | Assuming the path is found to exist (ENOENT would not be returned) use the drive with the most free space available. |
|
||||||
| epmfs (existing path, most free space) | If the path exists in multiple locations use the one with the most free space. Otherwise fall back to mfs. |
|
| epmfs (existing path, most free space) | If the path exists in multiple locations use the one with the most free space. Otherwise fall back to mfs. |
|
||||||
| rand (random) | Pick a destination at random. Again the dirname of the full path must exist somewhere. |
|
| rand (random) | Pick an existing destination at random. |
|
||||||
|
|
||||||
#### statvfs ####
|
#### statvfs ####
|
||||||
|
|
||||||
|
@ -51,13 +51,13 @@ _access(const fs::SearchFunc searchFunc,
|
|||||||
const int mask)
|
const int mask)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector path;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,path);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = ::eaccess(path[0].full.c_str(),mask);
|
rv = ::eaccess(path.full.c_str(),mask);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
@ -45,24 +45,15 @@ _chmod(const fs::SearchFunc searchFunc,
|
|||||||
const mode_t mode)
|
const mode_t mode)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::chmod(path.full.c_str(),mode);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::chmod(i->full.c_str(),mode);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -47,24 +47,15 @@ _chown(const fs::SearchFunc searchFunc,
|
|||||||
const gid_t gid)
|
const gid_t gid)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::lchown(path.full.c_str(),uid,gid);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::lchown(i->full.c_str(),uid,gid);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -57,8 +57,8 @@ _create(const fs::SearchFunc searchFunc,
|
|||||||
int rv;
|
int rv;
|
||||||
string path;
|
string path;
|
||||||
string dirname;
|
string dirname;
|
||||||
fs::PathVector createpath;
|
fs::Path createpath;
|
||||||
fs::PathVector existingpath;
|
fs::Path existingpath;
|
||||||
|
|
||||||
dirname = fs::dirname(fusepath);
|
dirname = fs::dirname(fusepath);
|
||||||
rv = searchFunc(srcmounts,dirname,existingpath);
|
rv = searchFunc(srcmounts,dirname,existingpath);
|
||||||
@ -69,13 +69,13 @@ _create(const fs::SearchFunc searchFunc,
|
|||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if(createpath[0].base != existingpath[0].base)
|
if(createpath.base != existingpath.base)
|
||||||
{
|
{
|
||||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||||
fs::clonepath(existingpath[0].base,createpath[0].base,dirname);
|
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::make_path(createpath[0].base,fusepath);
|
path = fs::make_path(createpath.base,fusepath);
|
||||||
|
|
||||||
fd = ::open(path.c_str(),flags,mode);
|
fd = ::open(path.c_str(),flags,mode);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
|
122
src/fs.cpp
122
src/fs.cpp
@ -500,7 +500,7 @@ namespace fs
|
|||||||
int
|
int
|
||||||
invalid(const vector<string> &basepaths,
|
invalid(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &rv)
|
||||||
{
|
{
|
||||||
return (errno = EINVAL,-1);
|
return (errno = EINVAL,-1);
|
||||||
}
|
}
|
||||||
@ -508,7 +508,7 @@ namespace fs
|
|||||||
int
|
int
|
||||||
ff(const vector<string> &basepaths,
|
ff(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
for(vector<string>::const_iterator
|
for(vector<string>::const_iterator
|
||||||
@ -517,13 +517,18 @@ namespace fs
|
|||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string path;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
path = fs::make_path(*iter,fusepath);
|
fullpath = fs::make_path(*iter,fusepath);
|
||||||
rv = ::lstat(path.c_str(),&st);
|
|
||||||
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
return (paths.push_back(Path(*iter,path)),0);
|
{
|
||||||
|
path.base = *iter;
|
||||||
|
path.full = fullpath;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -532,7 +537,7 @@ namespace fs
|
|||||||
int
|
int
|
||||||
ffwp(const vector<string> &basepaths,
|
ffwp(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
Path fallback;
|
Path fallback;
|
||||||
|
|
||||||
@ -543,24 +548,27 @@ namespace fs
|
|||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string path;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
path = fs::make_path(*iter,fusepath);
|
fullpath = fs::make_path(*iter,fusepath);
|
||||||
rv = ::lstat(path.c_str(),&st);
|
|
||||||
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
{
|
{
|
||||||
return (paths.push_back(Path(*iter,path)),0);
|
path.base = *iter;
|
||||||
|
path.full = fullpath;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if(errno == EACCES)
|
else if(errno == EACCES)
|
||||||
{
|
{
|
||||||
fallback.base = *iter;
|
fallback.base = *iter;
|
||||||
fallback.full = path;
|
fallback.full = fullpath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fallback.base.empty())
|
if(!fallback.base.empty())
|
||||||
return (paths.push_back(fallback),0);
|
return (path = fallback,0);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -568,7 +576,7 @@ namespace fs
|
|||||||
int
|
int
|
||||||
newest(const vector<string> &basepaths,
|
newest(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
time_t newest;
|
time_t newest;
|
||||||
string npath;
|
string npath;
|
||||||
@ -583,68 +591,46 @@ namespace fs
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const string path = fs::make_path(*iter,fusepath);
|
string fullpath;
|
||||||
|
|
||||||
rv = ::lstat(path.c_str(),&st);
|
fullpath = fs::make_path(*iter,fusepath);
|
||||||
|
|
||||||
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == 0 && st.st_mtime > newest)
|
if(rv == 0 && st.st_mtime > newest)
|
||||||
{
|
{
|
||||||
newest = st.st_mtime;
|
newest = st.st_mtime;
|
||||||
niter = iter;
|
niter = iter;
|
||||||
npath = path;
|
npath = fullpath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newest)
|
if(newest)
|
||||||
return (paths.push_back(Path(*niter,npath)),0);
|
{
|
||||||
|
path.base = *niter;
|
||||||
|
path.full = npath;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
all(const vector<string> &basepaths,
|
|
||||||
const string &fusepath,
|
|
||||||
PathVector &paths)
|
|
||||||
{
|
|
||||||
errno = ENOENT;
|
|
||||||
for(vector<string>::const_iterator
|
|
||||||
iter = basepaths.begin(), eiter = basepaths.end();
|
|
||||||
iter != eiter;
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
string path;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
path = fs::make_path(*iter,fusepath);
|
|
||||||
rv = ::lstat(path.c_str(),&st);
|
|
||||||
if(rv == 0)
|
|
||||||
paths.push_back(Path(*iter,path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths.empty() ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mfs(const vector<string> &basepaths,
|
mfs(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
fsblkcnt_t mfs;
|
fsblkcnt_t mfs;
|
||||||
string mfspath;
|
size_t mfsidx;
|
||||||
string fullmfspath;
|
|
||||||
|
|
||||||
mfs = 0;
|
mfs = 0;
|
||||||
errno = ENOENT;
|
for(size_t i = 0, size = basepaths.size();
|
||||||
for(vector<string>::const_iterator
|
i != size;
|
||||||
iter = basepaths.begin(), eiter = basepaths.end();
|
i++)
|
||||||
iter != eiter;
|
|
||||||
++iter)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct statvfs fsstats;
|
struct statvfs fsstats;
|
||||||
const string &mountpoint = *iter;
|
|
||||||
|
|
||||||
rv = ::statvfs(mountpoint.c_str(),&fsstats);
|
rv = ::statvfs(basepaths[i].c_str(),&fsstats);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
{
|
{
|
||||||
fsblkcnt_t spaceavail;
|
fsblkcnt_t spaceavail;
|
||||||
@ -653,17 +639,16 @@ namespace fs
|
|||||||
if(spaceavail > mfs)
|
if(spaceavail > mfs)
|
||||||
{
|
{
|
||||||
mfs = spaceavail;
|
mfs = spaceavail;
|
||||||
mfspath = mountpoint;
|
mfsidx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mfs == 0)
|
if(mfs == 0)
|
||||||
return -1;
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
fullmfspath = fs::make_path(mfspath,fusepath);
|
path.base = basepaths[mfsidx];
|
||||||
|
path.full = fs::make_path(path.base,fusepath);
|
||||||
paths.push_back(Path(mfspath,fullmfspath));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -671,11 +656,11 @@ namespace fs
|
|||||||
int
|
int
|
||||||
epmfs(const vector<string> &basepaths,
|
epmfs(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
fsblkcnt_t existingmfs = 0;
|
fsblkcnt_t existingmfs = 0;
|
||||||
fsblkcnt_t generalmfs = 0;
|
fsblkcnt_t generalmfs = 0;
|
||||||
string path;
|
string fullpath;
|
||||||
string generalmfspath;
|
string generalmfspath;
|
||||||
string existingmfspath;
|
string existingmfspath;
|
||||||
vector<string>::const_iterator iter = basepaths.begin();
|
vector<string>::const_iterator iter = basepaths.begin();
|
||||||
@ -703,8 +688,8 @@ namespace fs
|
|||||||
generalmfspath = mountpoint;
|
generalmfspath = mountpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::make_path(mountpoint,fusepath);
|
fullpath = fs::make_path(mountpoint,fusepath);
|
||||||
rv = ::lstat(path.c_str(),&st);
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
{
|
{
|
||||||
if(spaceavail > existingmfs)
|
if(spaceavail > existingmfs)
|
||||||
@ -722,7 +707,8 @@ namespace fs
|
|||||||
if(existingmfspath.empty())
|
if(existingmfspath.empty())
|
||||||
existingmfspath = generalmfspath;
|
existingmfspath = generalmfspath;
|
||||||
|
|
||||||
paths.push_back(Path(existingmfspath,path));
|
path.base = existingmfspath;
|
||||||
|
path.full = fullpath;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -730,19 +716,13 @@ namespace fs
|
|||||||
int
|
int
|
||||||
rand(const vector<string> &basepaths,
|
rand(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths)
|
Path &path)
|
||||||
{
|
{
|
||||||
string randombasepath;
|
path.base = *random_element(basepaths.begin(),
|
||||||
string randomfullpath;
|
|
||||||
|
|
||||||
randombasepath = *random_element(basepaths.begin(),
|
|
||||||
basepaths.end());
|
basepaths.end());
|
||||||
|
path.full = fs::make_path(path.base,
|
||||||
randomfullpath = fs::make_path(randombasepath,
|
|
||||||
fusepath);
|
fusepath);
|
||||||
|
|
||||||
paths.push_back(Path(randombasepath,randomfullpath));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
src/fs.hpp
20
src/fs.hpp
@ -48,8 +48,7 @@ namespace fs
|
|||||||
string full;
|
string full;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<Path> PathVector;
|
typedef int (*SearchFunc)(const vector<string>&,const string&,Path&);
|
||||||
typedef int (*SearchFunc)(const vector<string>&,const string&,PathVector&);
|
|
||||||
|
|
||||||
string dirname(const string &path);
|
string dirname(const string &path);
|
||||||
string basename(const string &path);
|
string basename(const string &path);
|
||||||
@ -114,28 +113,25 @@ namespace fs
|
|||||||
{
|
{
|
||||||
int invalid(const vector<string> &basepaths,
|
int invalid(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths);
|
Path &path);
|
||||||
int ff(const vector<string> &basepaths,
|
int ff(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &paths);
|
Path &path);
|
||||||
int ffwp(const vector<string> &paths,
|
int ffwp(const vector<string> &paths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &rv);
|
Path &path);
|
||||||
int newest(const vector<string> &paths,
|
int newest(const vector<string> &paths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &rv);
|
Path &path);
|
||||||
int all(const vector<string> &paths,
|
|
||||||
const string &fusepath,
|
|
||||||
PathVector &rv);
|
|
||||||
int mfs(const vector<string> &paths,
|
int mfs(const vector<string> &paths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &rv);
|
Path &path);
|
||||||
int epmfs(const vector<string> &paths,
|
int epmfs(const vector<string> &paths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &rv);
|
Path &path);
|
||||||
int rand(const vector<string> &paths,
|
int rand(const vector<string> &paths,
|
||||||
const string &fusepath,
|
const string &fusepath,
|
||||||
PathVector &rv);
|
Path &path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,13 +71,13 @@ _getattr(const fs::SearchFunc searchFunc,
|
|||||||
struct stat &buf)
|
struct stat &buf)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = ::lstat(paths[0].full.c_str(),&buf);
|
rv = ::lstat(path.full.c_str(),&buf);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
@ -107,18 +107,18 @@ _getxattr(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
#ifndef WITHOUT_XATTR
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if(!strcmp(attrname,"user.mergerfs.basepath"))
|
if(!strcmp(attrname,"user.mergerfs.basepath"))
|
||||||
rv = ::_getxattr_from_string(buf,count,paths[0].base);
|
rv = ::_getxattr_from_string(buf,count,path.base);
|
||||||
else if(!strcmp(attrname,"user.mergerfs.fullpath"))
|
else if(!strcmp(attrname,"user.mergerfs.fullpath"))
|
||||||
rv = ::_getxattr_from_string(buf,count,paths[0].full);
|
rv = ::_getxattr_from_string(buf,count,path.full);
|
||||||
else
|
else
|
||||||
rv = ::lgetxattr(paths[0].full.c_str(),attrname,buf,count);
|
rv = ::lgetxattr(path.full.c_str(),attrname,buf,count);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : rv);
|
return ((rv == -1) ? -errno : rv);
|
||||||
#else
|
#else
|
||||||
|
@ -93,13 +93,13 @@ _ioctl_dir_base(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fd = ::open(paths[0].full.c_str(),flags);
|
fd = ::open(path.full.c_str(),flags);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
40
src/link.cpp
40
src/link.cpp
@ -47,47 +47,35 @@ _link(const fs::SearchFunc searchFunc,
|
|||||||
const string &to)
|
const string &to)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,from,paths);
|
rv = searchFunc(srcmounts,from,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
const string pathfrom = fs::make_path(path.base,from);
|
||||||
error = 0;
|
const string pathto = fs::make_path(path.base,to);
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
int lrv;
|
|
||||||
const string pathfrom = fs::make_path(i->base,from);
|
|
||||||
const string pathto = fs::make_path(i->base,to);
|
|
||||||
|
|
||||||
lrv = ::link(pathfrom.c_str(),pathto.c_str());
|
rv = ::link(pathfrom.c_str(),pathto.c_str());
|
||||||
if(lrv == -1 && errno == ENOENT)
|
if(rv == -1 && errno == ENOENT)
|
||||||
{
|
{
|
||||||
string todir;
|
string todir;
|
||||||
fs::PathVector topaths;
|
fs::Path foundpath;
|
||||||
|
|
||||||
todir = fs::dirname(to);
|
todir = fs::dirname(to);
|
||||||
fs::find::ffwp(srcmounts,todir,topaths);
|
rv = fs::find::ffwp(srcmounts,todir,foundpath);
|
||||||
if(topaths.size() > 0)
|
if(rv == -1)
|
||||||
{
|
return -errno;
|
||||||
|
|
||||||
{
|
{
|
||||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||||
fs::clonepath(topaths[0].base,i->base,todir);
|
fs::clonepath(foundpath.base,path.base,todir);
|
||||||
}
|
}
|
||||||
|
|
||||||
lrv = ::link(pathfrom.c_str(),pathto.c_str());
|
rv = ::link(pathfrom.c_str(),pathto.c_str());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv &= lrv;
|
return ((rv == -1) ? -errno : 0);
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -75,13 +75,13 @@ _listxattr(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
#ifndef WITHOUT_XATTR
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = ::llistxattr(paths[0].full.c_str(),list,size);
|
rv = ::llistxattr(path.full.c_str(),list,size);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : rv);
|
return ((rv == -1) ? -errno : rv);
|
||||||
#else
|
#else
|
||||||
|
@ -51,8 +51,8 @@ _mkdir(const fs::SearchFunc searchFunc,
|
|||||||
int rv;
|
int rv;
|
||||||
string path;
|
string path;
|
||||||
string dirname;
|
string dirname;
|
||||||
fs::PathVector createpath;
|
fs::Path createpath;
|
||||||
fs::PathVector existingpath;
|
fs::Path existingpath;
|
||||||
|
|
||||||
if(fs::path_exists(srcmounts,fusepath))
|
if(fs::path_exists(srcmounts,fusepath))
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
@ -63,13 +63,16 @@ _mkdir(const fs::SearchFunc searchFunc,
|
|||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = createPathFunc(srcmounts,dirname,createpath);
|
rv = createPathFunc(srcmounts,dirname,createpath);
|
||||||
if(createpath[0].base != existingpath[0].base)
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if(createpath.base != existingpath.base)
|
||||||
{
|
{
|
||||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||||
fs::clonepath(existingpath[0].base,createpath[0].base,dirname);
|
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::make_path(createpath[0].base,fusepath);
|
path = fs::make_path(createpath.base,fusepath);
|
||||||
|
|
||||||
rv = ::mkdir(path.c_str(),mode);
|
rv = ::mkdir(path.c_str(),mode);
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ _mknod(const fs::SearchFunc searchFunc,
|
|||||||
int rv;
|
int rv;
|
||||||
string path;
|
string path;
|
||||||
string dirname;
|
string dirname;
|
||||||
fs::PathVector createpath;
|
fs::Path createpath;
|
||||||
fs::PathVector existingpath;
|
fs::Path existingpath;
|
||||||
|
|
||||||
if(fs::path_exists(srcmounts,fusepath))
|
if(fs::path_exists(srcmounts,fusepath))
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
@ -64,14 +64,17 @@ _mknod(const fs::SearchFunc searchFunc,
|
|||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
createPathFunc(srcmounts,dirname,createpath);
|
rv = createPathFunc(srcmounts,dirname,createpath);
|
||||||
if(existingpath[0].base != createpath[0].base)
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if(existingpath.base != createpath.base)
|
||||||
{
|
{
|
||||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||||
fs::clonepath(existingpath[0].base,createpath[0].base,dirname);
|
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
path = fs::make_path(createpath[0].base,fusepath);
|
path = fs::make_path(createpath.base,fusepath);
|
||||||
|
|
||||||
rv = ::mknod(path.c_str(),mode,dev);
|
rv = ::mknod(path.c_str(),mode,dev);
|
||||||
|
|
||||||
|
@ -51,17 +51,17 @@ _open(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fd = ::open(paths[0].full.c_str(),flags);
|
fd = ::open(path.full.c_str(),flags);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fh = (uint64_t)new FileInfo(fd,flags,paths[0].full);
|
fh = (uint64_t)new FileInfo(fd,flags,path.full);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ namespace mergerfs
|
|||||||
const std::vector<Policy> Policy::_policies_ =
|
const std::vector<Policy> Policy::_policies_ =
|
||||||
buildvector<Policy,true>
|
buildvector<Policy,true>
|
||||||
(POLICY(invalid))
|
(POLICY(invalid))
|
||||||
(POLICY(all))
|
|
||||||
(POLICY(epmfs))
|
(POLICY(epmfs))
|
||||||
(POLICY(ff))
|
(POLICY(ff))
|
||||||
(POLICY(ffwp))
|
(POLICY(ffwp))
|
||||||
@ -46,7 +45,6 @@ namespace mergerfs
|
|||||||
const Policy * const Policy::policies = &_policies_[1];
|
const Policy * const Policy::policies = &_policies_[1];
|
||||||
|
|
||||||
const Policy &Policy::invalid = Policy::policies[Policy::Enum::invalid];
|
const Policy &Policy::invalid = Policy::policies[Policy::Enum::invalid];
|
||||||
const Policy &Policy::all = Policy::policies[Policy::Enum::all];
|
|
||||||
const Policy &Policy::epmfs = Policy::policies[Policy::Enum::epmfs];
|
const Policy &Policy::epmfs = Policy::policies[Policy::Enum::epmfs];
|
||||||
const Policy &Policy::ff = Policy::policies[Policy::Enum::ff];
|
const Policy &Policy::ff = Policy::policies[Policy::Enum::ff];
|
||||||
const Policy &Policy::ffwp = Policy::policies[Policy::Enum::ffwp];
|
const Policy &Policy::ffwp = Policy::policies[Policy::Enum::ffwp];
|
||||||
|
@ -41,8 +41,7 @@ namespace mergerfs
|
|||||||
{
|
{
|
||||||
invalid = -1,
|
invalid = -1,
|
||||||
BEGIN = 0,
|
BEGIN = 0,
|
||||||
all = BEGIN,
|
epmfs = BEGIN,
|
||||||
epmfs,
|
|
||||||
ff,
|
ff,
|
||||||
ffwp,
|
ffwp,
|
||||||
mfs,
|
mfs,
|
||||||
@ -101,7 +100,6 @@ namespace mergerfs
|
|||||||
static const std::vector<Policy> _policies_;
|
static const std::vector<Policy> _policies_;
|
||||||
static const Policy * const policies;
|
static const Policy * const policies;
|
||||||
static const Policy &invalid;
|
static const Policy &invalid;
|
||||||
static const Policy &all;
|
|
||||||
static const Policy &epmfs;
|
static const Policy &epmfs;
|
||||||
static const Policy &ff;
|
static const Policy &ff;
|
||||||
static const Policy &ffwp;
|
static const Policy &ffwp;
|
||||||
|
@ -48,13 +48,13 @@ _readlink(const fs::SearchFunc searchFunc,
|
|||||||
const size_t size)
|
const size_t size)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = ::readlink(paths[0].full.c_str(),buf,size);
|
rv = ::readlink(path.full.c_str(),buf,size);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -48,24 +48,15 @@ _removexattr(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
#ifndef WITHOUT_XATTR
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::lremovexattr(path.full.c_str(),attrname);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::lremovexattr(i->full.c_str(),attrname);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
#else
|
#else
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,15 +48,15 @@ _rename(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string pathto;
|
string pathto;
|
||||||
fs::PathVector pathfrom;
|
fs::Path pathfrom;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,from,pathfrom);
|
rv = searchFunc(srcmounts,from,pathfrom);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
pathto = fs::make_path(pathfrom[0].base,to);
|
pathto = fs::make_path(pathfrom.base,to);
|
||||||
|
|
||||||
rv = ::rename(pathfrom[0].full.c_str(),pathto.c_str());
|
rv = ::rename(pathfrom.full.c_str(),pathto.c_str());
|
||||||
if(rv == -1 && errno == ENOENT)
|
if(rv == -1 && errno == ENOENT)
|
||||||
return -EXDEV;
|
return -EXDEV;
|
||||||
|
|
||||||
|
@ -45,24 +45,15 @@ _rmdir(const fs::SearchFunc searchFunc,
|
|||||||
const string &fusepath)
|
const string &fusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::rmdir(path.full.c_str());
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::rmdir(i->full.c_str());
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -234,24 +234,15 @@ _setxattr(const fs::SearchFunc searchFunc,
|
|||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
#ifndef WITHOUT_XATTR
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::lsetxattr(path.full.c_str(),attrname,attrval,attrvalsize,flags);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::lsetxattr(i->full.c_str(),attrname,attrval,attrvalsize,flags);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
#else
|
#else
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,15 +44,15 @@ _symlink(const vector<string> &srcmounts,
|
|||||||
const string &to)
|
const string &to)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
fs::PathVector paths;
|
fs::Path path;
|
||||||
|
|
||||||
fs::find::ff(srcmounts,fs::dirname(to),paths);
|
rv = fs::find::ff(srcmounts,fs::dirname(to),path);
|
||||||
if(paths.empty())
|
if(rv == -1)
|
||||||
return -ENOENT;
|
return -errno;
|
||||||
|
|
||||||
paths[0].full = fs::make_path(paths[0].base,to);
|
path.full = fs::make_path(path.base,to);
|
||||||
|
|
||||||
rv = symlink(from.c_str(),paths[0].full.c_str());
|
rv = symlink(from.c_str(),path.full.c_str());
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
@ -47,24 +47,15 @@ _truncate(const fs::SearchFunc searchFunc,
|
|||||||
const off_t size)
|
const off_t size)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::truncate(path.full.c_str(),size);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::truncate(i->full.c_str(),size);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -45,24 +45,15 @@ _unlink(const fs::SearchFunc searchFunc,
|
|||||||
const string &fusepath)
|
const string &fusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::unlink(path.full.c_str());
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::unlink(i->full.c_str());
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
@ -47,24 +47,15 @@ _utimens(const fs::SearchFunc searchFunc,
|
|||||||
const struct timespec ts[2])
|
const struct timespec ts[2])
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
fs::Path path;
|
||||||
fs::PathVector paths;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,paths);
|
rv = searchFunc(srcmounts,fusepath,path);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = -1;
|
rv = ::utimensat(0,path.full.c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
||||||
error = 0;
|
|
||||||
for(fs::PathVector::const_iterator
|
|
||||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
|
||||||
{
|
|
||||||
rv &= ::utimensat(0,i->full.c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
|
||||||
if(rv == -1)
|
|
||||||
error = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((rv == -1) ? -error : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user