mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-02-21 15:49:40 +08:00
remove statfs policy
This commit is contained in:
parent
29ed2bca01
commit
16fe0cf90c
40
README.md
40
README.md
@ -10,20 +10,19 @@ Why create mergerfs when those exist? mhddfs isn't really maintained or flexible
|
||||
Policies
|
||||
========
|
||||
|
||||
Filesystem calls are broken up into 5 classes of policies: search, action, create, statfs, and none.
|
||||
Filesystem calls are broken up into 4 categories of policies: search, action, create, and none.
|
||||
|
||||
Below shows each policy class, the FUSE calls they impact, and the policy names.
|
||||
|
||||
####Policy classifications####
|
||||
#### Policy classifications ####
|
||||
| Class | FUSE calls | Policies |
|
||||
|-------|------------|----------|
|
||||
| search | access, getattr, getxattr, listxattr, open, readlink | First Found (ff), First Found w/ Permission (ffwp), Newest (newest) |
|
||||
| action | chmod, link, removexattr, rmdir, setxattr, truncate, unlink, utimens | First Found (ff), First Found w/ Permission (ffwp), Newest (newest), All Found (all) |
|
||||
| create | create, mkdir, mknod | Existing Path (ep), Most Free Space (mfs), Existing Path Most Free Space (epmfs), Random (rand) |
|
||||
| statfs | statfs | Sum Used Max Free (sumf), Sum Used Sum Free (susf) |
|
||||
| none | fallocate, fsync, ftruncate, ioctl, read, readdir, rename, symlink, write, release | |
|
||||
| none | fallocate, fsync, ftruncate, ioctl, read, readdir, rename, statfs, symlink, write, release | |
|
||||
|
||||
####Descriptions####
|
||||
#### Descriptions ####
|
||||
| Class/Policy | Description |
|
||||
|--------------|-------------|
|
||||
| search/ff | Given the order the paths were provided at mount time act on the first one found (regardless if stat would return EACCES). |
|
||||
@ -37,8 +36,10 @@ Below shows each policy class, the FUSE calls they impact, and the policy names.
|
||||
| create/mfs | Assuming the path is found to exist (ENOENT would not be returned) use the drive with the most free space available. |
|
||||
| create/epmfs | If the path exists in multiple locations use the one with the most free space. Otherwise fall back to mfs. |
|
||||
| create/rand | Pick a destination at random. Again the dirname of the full path must exist somewhere. |
|
||||
| statfs/sumf | When reporting the size of the filesystem it will show the sum of all used but the available space will be reported as the max available across the filesystems mounted. |
|
||||
| statfs/susf | As above but will report the sum of available space. Since the largest usable space is that of the filesystem with the most usable space this option is deceptive. |
|
||||
|
||||
#### statvfs ####
|
||||
|
||||
Since we aren't trying to stripe data across drives the free space of the mountpoint is just that of the source mount with the most free space at the moment.
|
||||
|
||||
**NOTE:** create is really a search for existence and then create. The 'search' policy applies to the first part. If the [dirname](http://linux.die.net/man/3/dirname) of the full path is not found to exist [ENOENT](http://linux.die.net/man/3/errno) is returned.
|
||||
|
||||
@ -46,7 +47,7 @@ Usage
|
||||
=====
|
||||
|
||||
```
|
||||
$ mergerfs -o create=epmfs,search=ff,action=ff,statfs=sumf <mountpoint> <dir0>:<dir1>:<dir2>
|
||||
$ mergerfs -o create=epmfs,search=ff,action=ff <mountpoint> <dir0>:<dir1>:<dir2>
|
||||
```
|
||||
|
||||
| Option | Values | Default |
|
||||
@ -54,7 +55,6 @@ $ mergerfs -o create=epmfs,search=ff,action=ff,statfs=sumf <mountpoint> <dir0>:<
|
||||
| search | ff, ffwp, newest | ff |
|
||||
| action | ff, ffwp, newest, all | ff |
|
||||
| create | ep, mfs, epmfs, rand | epmfs |
|
||||
| statfs | sumf, susf | sumf |
|
||||
|
||||
Building
|
||||
========
|
||||
@ -72,6 +72,7 @@ make WITHOUT_XATTR=1 - to build program without xattrs functionality
|
||||
Runtime Settings
|
||||
================
|
||||
|
||||
#### /.mergerfs pseudo file ####
|
||||
```
|
||||
<mountpoint>/.mergerfs
|
||||
```
|
||||
@ -85,7 +86,6 @@ Reading the file will result in a newline delimited list of current settings as
|
||||
action=ff
|
||||
create=epmfs
|
||||
search=ff
|
||||
statfs=sumf
|
||||
```
|
||||
|
||||
Writing to the file is buffered and waits till a newline to process. Meaning echo works well.
|
||||
@ -96,7 +96,25 @@ Writing to the file is buffered and waits till a newline to process. Meaning ech
|
||||
action=ff
|
||||
create=epmfs
|
||||
search=newest
|
||||
statfs=sumf
|
||||
```
|
||||
|
||||
*NOTE:* offset is not supported and ignored in both read and write. There is also a safety check which limits buffered + incoming length to a max of 1024 bytes.
|
||||
|
||||
#### xattrs ####
|
||||
|
||||
If xattrs has been enabled you can also use [{list,get,set}xattrs](http://linux.die.net/man/2/listxattr) on the pseudo file **.mergerfs** to modify the policies. The keys are **mergerfs.action**, **mergerfs.create**, and **mergerfs.search**.
|
||||
|
||||
```
|
||||
[trapexit:/tmp/mount] $ attr -l .mergerfs
|
||||
Attribute "mergerfs.action" has a 3 byte value for .mergerfs
|
||||
Attribute "mergerfs.create" has a 6 byte value for .mergerfs
|
||||
Attribute "mergerfs.search" has a 3 byte value for .mergerfs
|
||||
|
||||
[trapexit:/tmp/mount] $ attr -g mergerfs.action .mergerfs
|
||||
Attribute "mergerfs.action" had a 3 byte value for .mergerfs:
|
||||
ff
|
||||
|
||||
[trapexit:/tmp/mount] 1 $ attr -s mergerfs.action -V ffwp .mergerfs
|
||||
Attribute "mergerfs.action" set to a 3 byte value for .mergerfs:
|
||||
ffwp
|
||||
```
|
||||
|
@ -63,8 +63,7 @@ namespace mergerfs
|
||||
|
||||
ss << "action=" << policy.action.str() << std::endl
|
||||
<< "create=" << policy.create.str() << std::endl
|
||||
<< "search=" << policy.search.str() << std::endl
|
||||
<< "statfs=" << policy.statfs.str() << std::endl;
|
||||
<< "search=" << policy.search.str() << std::endl;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
@ -56,8 +56,6 @@ _getxattr_controlfile(const Policy &policy,
|
||||
attrvalue = policy.create.str();
|
||||
else if(attrname == "user.mergerfs.search")
|
||||
attrvalue = policy.search.str();
|
||||
else if(attrname == "user.mergerfs.statfs")
|
||||
attrvalue = policy.statfs.str();
|
||||
|
||||
if(attrvalue.empty())
|
||||
return -ENOATTR;
|
||||
|
@ -68,9 +68,7 @@ process_opt(config::Config &config,
|
||||
switch(argvalue.size())
|
||||
{
|
||||
case 2:
|
||||
if(argvalue[0] == "statfs")
|
||||
policy.statfs.fromString(argvalue[1]);
|
||||
else if(argvalue[0] == "create")
|
||||
if(argvalue[0] == "create")
|
||||
policy.create.fromString(argvalue[1]);
|
||||
else if(argvalue[0] == "search")
|
||||
policy.search.fromString(argvalue[1]);
|
||||
|
@ -254,53 +254,4 @@ namespace mergerfs
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Policy::StatFS::StatFS(const Policy::StatFS::Type value)
|
||||
{
|
||||
*this = value;
|
||||
}
|
||||
|
||||
Policy::StatFS&
|
||||
Policy::StatFS::operator=(Policy::StatFS::Type value)
|
||||
{
|
||||
_str = toString(value);
|
||||
_value = fromString(_str);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Policy::StatFS&
|
||||
Policy::StatFS::operator=(const std::string str)
|
||||
{
|
||||
_value = fromString(str);
|
||||
_str = toString(_value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Policy::StatFS::Type
|
||||
Policy::StatFS::fromString(const std::string str)
|
||||
{
|
||||
if(str == "susf")
|
||||
return Policy::StatFS::SumUsedSumFree;
|
||||
else if(str == "sumf")
|
||||
return Policy::StatFS::SumUsedMaxFree;
|
||||
|
||||
return Policy::StatFS::Invalid;
|
||||
}
|
||||
|
||||
std::string
|
||||
Policy::StatFS::toString(const Policy::StatFS::Type value)
|
||||
{
|
||||
switch(value)
|
||||
{
|
||||
case Policy::StatFS::SumUsedSumFree:
|
||||
return "susf";
|
||||
case Policy::StatFS::SumUsedMaxFree:
|
||||
return "sumf";
|
||||
case Policy::StatFS::Invalid:
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,45 +36,12 @@ namespace mergerfs
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
STATFS,
|
||||
ACTION,
|
||||
CREATE,
|
||||
SEARCH
|
||||
};
|
||||
|
||||
public:
|
||||
class StatFS
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Invalid = -1,
|
||||
SumUsedSumFree,
|
||||
SumUsedMaxFree,
|
||||
Max
|
||||
};
|
||||
|
||||
StatFS(Type _value);
|
||||
|
||||
public:
|
||||
operator Type() const { return _value; }
|
||||
operator std::string() const { return _str; }
|
||||
std::string str() const { return _str; }
|
||||
|
||||
StatFS& operator=(const Type);
|
||||
StatFS& operator=(const std::string);
|
||||
|
||||
static Type fromString(const std::string);
|
||||
static std::string toString(const Type);
|
||||
|
||||
private:
|
||||
StatFS();
|
||||
|
||||
private:
|
||||
Type _value;
|
||||
std::string _str;
|
||||
};
|
||||
|
||||
class Create
|
||||
{
|
||||
public:
|
||||
@ -190,14 +157,12 @@ namespace mergerfs
|
||||
|
||||
public:
|
||||
Policy() :
|
||||
statfs(StatFS::SumUsedMaxFree),
|
||||
create(Create::ExistingPathMostFreeSpace),
|
||||
search(Search::FirstFound),
|
||||
action(Action::FirstFound)
|
||||
{}
|
||||
|
||||
public:
|
||||
StatFS statfs;
|
||||
Create create;
|
||||
Search search;
|
||||
Action action;
|
||||
|
@ -75,15 +75,6 @@ _setxattr_controlfile(config::Config &config,
|
||||
else
|
||||
return -ENOSPC;
|
||||
}
|
||||
else if(attrname == "user.mergerfs.statfs")
|
||||
{
|
||||
if((flags & XATTR_CREATE) == XATTR_CREATE)
|
||||
return -EEXIST;
|
||||
if(Policy::StatFS::fromString(attrval) != -1)
|
||||
config.policy.statfs = attrval;
|
||||
else
|
||||
return -ENOSPC;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -ENOATTR;
|
||||
|
@ -68,24 +68,12 @@ _normalize_statvfs(struct statvfs *fsstat,
|
||||
static
|
||||
void
|
||||
_merge_statvfs(struct statvfs * const out,
|
||||
const struct statvfs * const in,
|
||||
const Policy::StatFS policy)
|
||||
const struct statvfs * const in)
|
||||
{
|
||||
switch(policy)
|
||||
if(out->f_bfree < in->f_bfree)
|
||||
{
|
||||
case Policy::StatFS::SumUsedMaxFree:
|
||||
if(out->f_bfree < in->f_bfree)
|
||||
{
|
||||
out->f_bfree = in->f_bfree;
|
||||
out->f_bavail = in->f_bavail;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case Policy::StatFS::SumUsedSumFree:
|
||||
out->f_bfree += in->f_bfree;
|
||||
out->f_bavail += in->f_bavail;
|
||||
break;
|
||||
out->f_bfree = in->f_bfree;
|
||||
out->f_bavail = in->f_bavail;
|
||||
}
|
||||
|
||||
out->f_ffree += in->f_ffree;
|
||||
@ -96,8 +84,7 @@ _merge_statvfs(struct statvfs * const out,
|
||||
|
||||
static
|
||||
int
|
||||
_statfs(const Policy::StatFS policy,
|
||||
const vector<string> &srcmounts,
|
||||
_statfs(const vector<string> &srcmounts,
|
||||
struct statvfs &fsstat)
|
||||
{
|
||||
unsigned long min_bsize = ULONG_MAX;
|
||||
@ -134,7 +121,7 @@ _statfs(const Policy::StatFS policy,
|
||||
for(;fsstatiter != endfsstatiter;++fsstatiter)
|
||||
{
|
||||
_normalize_statvfs(&fsstatiter->second,min_bsize,min_frsize,min_namemax);
|
||||
_merge_statvfs(&fsstat,&fsstatiter->second,policy);
|
||||
_merge_statvfs(&fsstat,&fsstatiter->second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,8 +139,7 @@ namespace mergerfs
|
||||
const ugid::SetResetGuard uid;
|
||||
const config::Config &config = config::get();
|
||||
|
||||
return _statfs(config.policy.statfs,
|
||||
config.srcmounts,
|
||||
return _statfs(config.srcmounts,
|
||||
*stat);
|
||||
}
|
||||
}
|
||||
|
@ -68,12 +68,6 @@ _process_kv(Config &config,
|
||||
if(rv == 0)
|
||||
config.policy.create = value;
|
||||
}
|
||||
else if(key == "statfs")
|
||||
{
|
||||
rv = (Policy::StatFS::fromString(value) != -1) ? 0 : -EINVAL;
|
||||
if(rv == 0)
|
||||
config.policy.statfs = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = -EINVAL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user