From 2e95c6e78ecbd85ed2e135b8bf96c92ce7fd756e Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Thu, 5 Feb 2015 18:23:01 -0500 Subject: [PATCH] merge action and search category --- README.md | 28 +++++++++++++++------------- src/category.cpp | 2 -- src/category.hpp | 4 +--- src/chmod.cpp | 2 +- src/chown.cpp | 2 +- src/config.cpp | 2 -- src/config.hpp | 1 - src/getxattr.cpp | 4 +--- src/link.cpp | 2 +- src/listxattr.cpp | 1 - src/option_parser.cpp | 2 -- src/removexattr.cpp | 2 +- src/rmdir.cpp | 2 +- src/setxattr.cpp | 2 +- src/truncate.cpp | 2 +- src/unlink.cpp | 2 +- src/utimens.cpp | 2 +- 17 files changed, 26 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index e3dc225c..9b5b1afb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ % mergerfs(1) mergerfs user manual % Antonio SJ Musumeci -% June 9, 2014 +% 2015-02-05 # NAME @@ -8,7 +8,7 @@ mergerfs - another FUSE union filesystem # SYNOPSIS -mergerfs -ocreate=epmfs,search=ff,action=ff <srcpoints> <mountpoint> +mergerfs -ocreate=epmfs,search=ff <srcpoints> <mountpoint> # DESCRIPTION @@ -23,7 +23,6 @@ Why create mergerfs when those exist? mhddfs isn't really maintained or flexible | Option | Default | |--------|--------| | search | ff | -| action | ff | | create | epmfs | ###srcpoints### @@ -47,13 +46,12 @@ In /etc/fstab it'd look like the following: # POLICIES -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**. +Filesystem calls are broken up into 2 categories: search 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**. #### Functional classifications #### | Class | FUSE calls | |-------|------------| -| search | access, getattr, getxattr, listxattr, open, readlink | -| action | chmod, link, removexattr, rmdir, setxattr, truncate, unlink, utimens | +| search | access, getattr, getxattr, listxattr, open, readlink, chmod, link, removexattr, rmdir, setxattr, truncate, unlink, utimens | | create | create, mkdir, mknod | | none | fallocate, fgetattr, fsync, ftruncate, ioctl, read, readdir, rename, statfs, symlink, write, release | @@ -67,11 +65,17 @@ Filesystem calls are broken up into 3 categories: search, action, and create. Th | 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 an existing destination at random. | +#### readdir #### + +[readdir](http://linux.die.net/man/3/readdir) is very different from most functions in this realm. It certainly could have it's own set of policies to tweak its behavior. At this time it provides a simple `first found` merging of directories and file found. That is: only the first file or directory found for a directory is returned. + +It could be extended to offer the ability to see all files found. Perhaps concatinating `#` and a number to the name. But to really be useful you'd need to be able to access them which would complicate file lookup. + #### statvfs #### -It normalizes the source drives based on the fragment size and sums the number of adjusted blocks and inodes. This means you will see the combined space of all sources. Total, used, and free. The sources however are dedupped based on the drive so multiple points on the same drive will not result in double counting it's space. +[statvfs](http://linux.die.net/man/2/statvfs) normalizes the source drives based on the fragment size and sums the number of adjusted blocks and inodes. This means you will see the combined space of all sources. Total, used, and free. The sources however are dedupped based on the drive so multiple points on the same drive will not result in double counting it's space. -**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. +**NOTE:** Since we can not (easily) replicate the atomicity of an `mkdir` or `mknod` without side effects those calls will first do a scan to see if the file exists and then attempts a create. This means there is a slight race condition. Worse case you'd end up with the directory or file on more than one mount. # BUILDING @@ -98,22 +102,20 @@ Even if xattrs are disabled the [{list,get,set}xattrs](http://linux.die.net/man/ The keys are: * user.mergerfs.srcmounts -* user.mergerfs.action * user.mergerfs.create * user.mergerfs.search ``` [trapexit:/tmp/mount] $ xattr -l .mergerfs user.mergerfs.srcmounts: /tmp/a:/tmp/b -user.mergerfs.action: ff user.mergerfs.create: epmfs user.mergerfs.search: ff -[trapexit:/tmp/mount] $ xattr -p user.mergerfs.action .mergerfs +[trapexit:/tmp/mount] $ xattr -p user.mergerfs.search .mergerfs ff -[trapexit:/tmp/mount] $ xattr -w user.mergerfs.action ffwp .mergerfs -[trapexit:/tmp/mount] $ xattr -p user.mergerfs.action .mergerfs +[trapexit:/tmp/mount] $ xattr -w user.mergerfs.search ffwp .mergerfs +[trapexit:/tmp/mount] $ xattr -p user.mergerfs.search .mergerfs ffwp [trapexit:/tmp/mount] $ xattr -w user.mergerfs.srcmounts +/tmp/c .mergerfs diff --git a/src/category.cpp b/src/category.cpp index 2c068345..df1e2d40 100644 --- a/src/category.cpp +++ b/src/category.cpp @@ -35,14 +35,12 @@ namespace mergerfs const std::vector Category::_categories_ = buildvector (CATEGORY(invalid)) - (CATEGORY(action)) (CATEGORY(create)) (CATEGORY(search)); const Category * const Category::categories = &_categories_[1]; const Category &Category::invalid = Category::categories[Category::Enum::invalid]; - const Category &Category::action = Category::categories[Category::Enum::action]; const Category &Category::create = Category::categories[Category::Enum::create]; const Category &Category::search = Category::categories[Category::Enum::search]; diff --git a/src/category.hpp b/src/category.hpp index 9b014e72..3bca5bc6 100644 --- a/src/category.hpp +++ b/src/category.hpp @@ -39,8 +39,7 @@ namespace mergerfs { invalid = -1, BEGIN = 0, - action = BEGIN, - create, + create = BEGIN, search, END }; @@ -89,7 +88,6 @@ namespace mergerfs static const std::vector _categories_; static const Category * const categories; static const Category &invalid; - static const Category &action; static const Category &create; static const Category &search; }; diff --git a/src/chmod.cpp b/src/chmod.cpp index a49c6ee0..7c9d9797 100644 --- a/src/chmod.cpp +++ b/src/chmod.cpp @@ -69,7 +69,7 @@ namespace mergerfs const config::Config &config = config::get(); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _chmod(*config.action, + return _chmod(*config.search, config.srcmounts, fusepath, mode); diff --git a/src/chown.cpp b/src/chown.cpp index 11c2ffcf..2609a1d3 100644 --- a/src/chown.cpp +++ b/src/chown.cpp @@ -72,7 +72,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _chown(*config.action, + return _chown(*config.search, config.srcmounts, fusepath, uid, diff --git a/src/config.cpp b/src/config.cpp index b0d76459..580c696c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -43,14 +43,12 @@ namespace mergerfs : destmount(), srcmounts(), srcmountslock(), - action(policies[Category::Enum::action]), create(policies[Category::Enum::create]), search(policies[Category::Enum::search]), controlfile("/.mergerfs") { pthread_rwlock_init(&srcmountslock,NULL); - action = &Policy::ff; create = &Policy::epmfs; search = &Policy::ff; } diff --git a/src/config.hpp b/src/config.hpp index a4f4f428..36aa1490 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -50,7 +50,6 @@ namespace mergerfs mutable pthread_rwlock_t srcmountslock; const Policy *policies[Category::Enum::END]; - const Policy *&action; const Policy *&create; const Policy *&search; diff --git a/src/getxattr.cpp b/src/getxattr.cpp index 076a9fa7..5e1c4dfd 100644 --- a/src/getxattr.cpp +++ b/src/getxattr.cpp @@ -52,9 +52,7 @@ _getxattr_controlfile(const Config &config, size_t len; string attrvalue; - if(attrname == "user.mergerfs.action") - attrvalue = (std::string)*config.action; - else if(attrname == "user.mergerfs.create") + if(attrname == "user.mergerfs.create") attrvalue = (std::string)*config.create; else if(attrname == "user.mergerfs.search") attrvalue = (std::string)*config.search; diff --git a/src/link.cpp b/src/link.cpp index 4d24107f..e19c2226 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -91,7 +91,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _link(*config.action, + return _link(*config.search, config.srcmounts, from, to); diff --git a/src/listxattr.cpp b/src/listxattr.cpp index b7bb8549..e6b7d2d0 100644 --- a/src/listxattr.cpp +++ b/src/listxattr.cpp @@ -49,7 +49,6 @@ _listxattr_controlfile(char *list, { const char xattrs[] = "user.mergerfs.srcmounts\0" - "user.mergerfs.action\0" "user.mergerfs.create\0" "user.mergerfs.search" ; diff --git a/src/option_parser.cpp b/src/option_parser.cpp index eb71ba14..861a2c7a 100644 --- a/src/option_parser.cpp +++ b/src/option_parser.cpp @@ -57,8 +57,6 @@ process_opt(config::Config &config, config.create = Policy::find(argvalue[1]); else if(argvalue[0] == "search") config.search = Policy::find(argvalue[1]); - else if(argvalue[0] == "action") - config.action = Policy::find(argvalue[1]); else rv = 1; break; diff --git a/src/removexattr.cpp b/src/removexattr.cpp index 066dd859..b4dd98a1 100644 --- a/src/removexattr.cpp +++ b/src/removexattr.cpp @@ -79,7 +79,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _removexattr(*config.action, + return _removexattr(*config.search, config.srcmounts, fusepath, attrname); diff --git a/src/rmdir.cpp b/src/rmdir.cpp index 37faa17f..c87e65a4 100644 --- a/src/rmdir.cpp +++ b/src/rmdir.cpp @@ -68,7 +68,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readguard(&config.srcmountslock); - return _rmdir(*config.action, + return _rmdir(*config.search, config.srcmounts, fusepath); } diff --git a/src/setxattr.cpp b/src/setxattr.cpp index 63ad21c8..4e1ca9cb 100644 --- a/src/setxattr.cpp +++ b/src/setxattr.cpp @@ -271,7 +271,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _setxattr(*config.action, + return _setxattr(*config.search, config.srcmounts, fusepath, attrname, diff --git a/src/truncate.cpp b/src/truncate.cpp index 55074647..4bd28280 100644 --- a/src/truncate.cpp +++ b/src/truncate.cpp @@ -71,7 +71,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _truncate(*config.action, + return _truncate(*config.search, config.srcmounts, fusepath, size); diff --git a/src/unlink.cpp b/src/unlink.cpp index 7ed1a55e..adf9c869 100644 --- a/src/unlink.cpp +++ b/src/unlink.cpp @@ -68,7 +68,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _unlink(*config.action, + return _unlink(*config.search, config.srcmounts, fusepath); } diff --git a/src/utimens.cpp b/src/utimens.cpp index cb7c6291..a9b3409b 100644 --- a/src/utimens.cpp +++ b/src/utimens.cpp @@ -71,7 +71,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _utimens(*config.action, + return _utimens(*config.search, config.srcmounts, fusepath, ts);