From f6e37c57fe0382302d1a96ce2cade95c152bff6a Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Sun, 27 Sep 2020 00:28:00 -0400 Subject: [PATCH] README.md: add details about error handling --- README.md | 61 ++++++++++++++++++++++-------- man/mergerfs.1 | 100 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 115 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 244c24f7..e23c2f79 100644 --- a/README.md +++ b/README.md @@ -410,6 +410,35 @@ The above behavior will help minimize the likelihood of EXDEV being returned but The options `statfs` and `statfs_ignore` can be used to modify `statfs` behavior. +# ERROR HANDLING + +POSIX filesystem functions offer a single return code meaning that there is some complication regarding the handling of multiple branches as mergerfs does. It tries to handle errors in a way that would generally return meaningful values for that particular function. + +### chmod, chown, removexattr, setxattr, truncate, utimens + +1) if no error: return 0 (success) +2) if no successes: return first error +3) if one of the files acted on was the same as the related search function: return its value +4) return 0 (success) + +While doing this increases the complexity and cost of error handling, particularly step 3, this provides probably the most reasonable return value. + + +### unlink, rmdir + +1) if no errors: return 0 (success) +2) return first error + +Older version of mergerfs would return success if any success occurred but for unlink and rmdir there are downstream assumptions that, while not impossible to occur, can confuse some software. + + +### others + +For search functions there is always a single thing acted on and as such whatever return value that comes from the single function call is returned. + +For create functions `mkdir`, `mknod`, and `symlink` which don't return a file descriptor and therefore can have `all` or `epall` policies it will return success if any of the calls succeed and an error otherwise. + + # BUILD / UPDATE **NOTE:** Prebuilt packages can be found at and recommended for most users: https://github.com/trapexit/mergerfs/releases @@ -462,6 +491,23 @@ make LTO=1 - build with link time optimization ``` +# UPGRADE + +mergerfs can be upgraded live by mounting on top of the previous instance. Simply install the new version of mergerfs and follow the instructions below. + +Add `nonempty` to your mergerfs option list and call mergerfs again or if using `/etc/fstab` call for it to mount again. Existing open files and such will continue to work fine though they won't see runtime changes since any such change would be the new mount. If you plan on changing settings with the new mount you should / could apply those before mounting the new version. + +``` +$ sudo mount /mnt/mergerfs +$ mount | grep mergerfs +media on /mnt/mergerfs type fuse.mergerfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) +media on /mnt/mergerfs type fuse.mergerfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) +``` + +A problem with this approach is that the underlying instance will continue to run even if the software using it stop or are restarted. To work around this you can use a "lazy umount". Before mounting over top the mount point with the new instance of mergerfs issue: `umount -l `. + + + # RUNTIME CONFIG #### ioctl @@ -593,20 +639,6 @@ A B C ``` -# UPGRADE - -mergerfs can be upgraded live by mounting on top of the previous version. Simply install the new version of mergerfs and follow the instructions below. - -Add `nonempty` to your mergerfs option list and call mergerfs again or if using `/etc/fstab` call for it to mount again. Existing open files and such will continue to work fine though they won't see runtime changes since any such change would be the new mount. If you plan on changing settings with the new mount you should / could apply those before mounting the new version. - -``` -$ sudo mount /mnt/mergerfs -$ mount | grep mergerfs -media on /mnt/mergerfs type fuse.mergerfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) -media on /mnt/mergerfs type fuse.mergerfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) -``` - - # TOOLING * https://github.com/trapexit/mergerfs-tools @@ -826,7 +858,6 @@ $ dd if=/mnt/mergerfs/1GB.file of=/dev/null bs=1M count=1024 iflag=nocache conv= * https://github.com/trapexit/backup-and-recovery-howtos : A set of guides / howtos on creating a data storage system, backing it up, maintaining it, and recovering from failure. * If you don't see some directories and files you expect in a merged point or policies seem to skip drives be sure the user has permission to all the underlying directories. Use `mergerfs.fsck` to audit the drive for out of sync permissions. * Do **not** use `cache.files=off` if you expect applications (such as rtorrent) to use [mmap](http://linux.die.net/man/2/mmap) files. Shared mmap is not currently supported in FUSE w/ page caching disabled. Enabling `dropcacheonclose` is recommended when `cache.files=partial|full|auto-full`. -* Since POSIX functions give only a singular error or success its difficult to determine the proper behavior when applying the function to multiple targets. **mergerfs** will return an error only if all attempts of an action fail. Any success will lead to a success returned. This means however that some odd situations may arise. * [Kodi](http://kodi.tv), [Plex](http://plex.tv), [Subsonic](http://subsonic.org), etc. can use directory [mtime](http://linux.die.net/man/2/stat) to more efficiently determine whether to scan for new content rather than simply performing a full scan. If using the default **getattr** policy of **ff** it's possible those programs will miss an update on account of it returning the first directory found's **stat** info and its a later directory on another mount which had the **mtime** recently updated. To fix this you will want to set **func.getattr=newest**. Remember though that this is just **stat**. If the file is later **open**'ed or **unlink**'ed and the policy is different for those then a completely different file or directory could be acted on. * Some policies mixed with some functions may result in strange behaviors. Not that some of these behaviors and race conditions couldn't happen outside **mergerfs** but that they are far more likely to occur on account of the attempt to merge together multiple sources of data which could be out of sync due to the different policies. * For consistency its generally best to set **category** wide policies rather than individual **func**'s. This will help limit the confusion of tools such as [rsync](http://linux.die.net/man/1/rsync). However, the flexibility is there if needed. diff --git a/man/mergerfs.1 b/man/mergerfs.1 index 6487ff69..124ac8d8 100644 --- a/man/mergerfs.1 +++ b/man/mergerfs.1 @@ -1075,6 +1075,46 @@ included when checking the mount\[aq]s stats. .PP The options \f[C]statfs\f[] and \f[C]statfs_ignore\f[] can be used to modify \f[C]statfs\f[] behavior. +.SH ERROR HANDLING +.PP +POSIX filesystem functions offer a single return code meaning that there +is some complication regarding the handling of multiple branches as +mergerfs does. +It tries to handle errors in a way that would generally return +meaningful values for that particular function. +.SS chmod, chown, removexattr, setxattr, truncate, utimens +.IP "1)" 3 +if no error: return 0 (success) +.IP "2)" 3 +if no successes: return first error +.IP "3)" 3 +if one of the files acted on was the same as the related search +function: return its value +.IP "4)" 3 +return 0 (success) +.PP +While doing this increases the complexity and cost of error handling, +particularly step 3, this provides probably the most reasonable return +value. +.SS unlink, rmdir +.IP "1)" 3 +if no errors: return 0 (success) +.IP "2)" 3 +return first error +.PP +Older version of mergerfs would return success if any success occurred +but for unlink and rmdir there are downstream assumptions that, while +not impossible to occur, can confuse some software. +.SS others +.PP +For search functions there is always a single thing acted on and as such +whatever return value that comes from the single function call is +returned. +.PP +For create functions \f[C]mkdir\f[], \f[C]mknod\f[], and +\f[C]symlink\f[] which don\[aq]t return a file descriptor and therefore +can have \f[C]all\f[] or \f[C]epall\f[] policies it will return success +if any of the calls succeed and an error otherwise. .SH BUILD / UPDATE .PP \f[B]NOTE:\f[] Prebuilt packages can be found at and recommended for @@ -1136,6 +1176,35 @@ make\ STATIC=1\ \ \ \ \ \ \ \ \ \-\ build\ static\ binary make\ LTO=1\ \ \ \ \ \ \ \ \ \ \ \ \-\ build\ with\ link\ time\ optimization \f[] .fi +.SH UPGRADE +.PP +mergerfs can be upgraded live by mounting on top of the previous +instance. +Simply install the new version of mergerfs and follow the instructions +below. +.PP +Add \f[C]nonempty\f[] to your mergerfs option list and call mergerfs +again or if using \f[C]/etc/fstab\f[] call for it to mount again. +Existing open files and such will continue to work fine though they +won\[aq]t see runtime changes since any such change would be the new +mount. +If you plan on changing settings with the new mount you should / could +apply those before mounting the new version. +.IP +.nf +\f[C] +$\ sudo\ mount\ /mnt/mergerfs +$\ mount\ |\ grep\ mergerfs +media\ on\ /mnt/mergerfs\ type\ fuse.mergerfs\ (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) +media\ on\ /mnt/mergerfs\ type\ fuse.mergerfs\ (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) +\f[] +.fi +.PP +A problem with this approach is that the underlying instance will +continue to run even if the software using it stop or are restarted. +To work around this you can use a "lazy umount". +Before mounting over top the mount point with the new instance of +mergerfs issue: \f[C]umount\ \-l\ \f[]. .SH RUNTIME CONFIG .SS ioctl .PP @@ -1346,29 +1415,6 @@ A\ B\ C /mnt/b/full/path/to/A \f[] .fi -.SH UPGRADE -.PP -mergerfs can be upgraded live by mounting on top of the previous -version. -Simply install the new version of mergerfs and follow the instructions -below. -.PP -Add \f[C]nonempty\f[] to your mergerfs option list and call mergerfs -again or if using \f[C]/etc/fstab\f[] call for it to mount again. -Existing open files and such will continue to work fine though they -won\[aq]t see runtime changes since any such change would be the new -mount. -If you plan on changing settings with the new mount you should / could -apply those before mounting the new version. -.IP -.nf -\f[C] -$\ sudo\ mount\ /mnt/mergerfs -$\ mount\ |\ grep\ mergerfs -media\ on\ /mnt/mergerfs\ type\ fuse.mergerfs\ (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) -media\ on\ /mnt/mergerfs\ type\ fuse.mergerfs\ (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other) -\f[] -.fi .SH TOOLING .IP \[bu] 2 https://github.com/trapexit/mergerfs\-tools @@ -1857,14 +1903,6 @@ Shared mmap is not currently supported in FUSE w/ page caching disabled. Enabling \f[C]dropcacheonclose\f[] is recommended when \f[C]cache.files=partial|full|auto\-full\f[]. .IP \[bu] 2 -Since POSIX functions give only a singular error or success its -difficult to determine the proper behavior when applying the function to -multiple targets. -\f[B]mergerfs\f[] will return an error only if all attempts of an action -fail. -Any success will lead to a success returned. -This means however that some odd situations may arise. -.IP \[bu] 2 Kodi (http://kodi.tv), Plex (http://plex.tv), Subsonic (http://subsonic.org), etc. can use directory mtime (http://linux.die.net/man/2/stat) to more