mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-20 00:17:43 +00:00
Reinstate the splice read/write/move paths removed in 84592a9f, now
gated behind runtime options with negotiated pipe sizing and fallback
logging.
- Transport: msgbuf-piped splice receive, fd-referenced splice reply
(vmsplice + splice), splice-move pipe-bounce, and restored
fuse_buf_copy/fuse_buf_flags plumbing for copy fallbacks
- Negotiation: new pipe-max-size option (auto-raised at INIT when
possible; the sysctl read/write is factored into src/pipe_max_size.cpp
so fuse_init.cpp and option_parser.cpp share one implementation);
fuse-msg-size clamped to what the pipe can hold; splice is disabled
at INIT with a warning if the sysctl can't fit even the minimum,
retracting the FUSE_CAP_SPLICE_* bits already advertised to the
kernel in that case
- Read replies and splice-move are gated at 128 KiB (below that the
syscalls cost more than the copy they avoid); every fallback path
degrades to the copy path and logs once per process via SysLog
- msgbuf pipe cache is process-global and mutex-guarded (mutex_lockguard)
so pipes can move between read and worker threads under
process-thread mode
- API simplified after review: collapsed the three per-axis options
(splice-read/write/move) into a single splice boolean (default on);
no-splice-read/write/move and the bare splice-read/write/move
spellings stay registered as accepted no-ops so existing mount
options don't fail the mount, but they do NOT alter the splice
knob - upgraders with no-splice-* in their config get splice
enabled and must set splice=false explicitly (see
deprecated_options.md)
- Fixed several correctness issues found in parallel review: a
dropped write_buf registration that silently corrupted writes, a
dirty-pipe reuse bug in msgbuf_free, an iov double-send in
fuse_reply_data's splice-move fallback, and pipe-capacity math that
assumed a 4096-byte page size
- Modernized the transport/negotiation code to this codebase's C++
style: RAII (unique_ptr/DEFER) instead of malloc/free and manual fd
close(), std::from_chars/to_chars instead of stoul/snprintf,
_ReplyPipe's pipe ops as methods instead of free functions closing
over a thread_local global, and vendored/libfuse/lib/buffer.cpp (a
near-verbatim port of upstream's buffer.c) brought in line with the
rest of the fork
- Documented splice and pipe-max-size options (mkdocs, FAQ,
deprecated-options list); added tools/bench-splice.sh
- Benchmarked on tmpfs: seq_write +21%, seq_read +52%, small_write
+5%, small_read +12%; validated with a 1h soak (~271 GiB
hash-verified I/O, zero integrity failures), a live-mount round-trip
of I/O above the splice threshold, and the existing unit/smoke
suites at their pre-existing baseline
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
13 KiB
13 KiB
Options
mergerfs has many options to control it many features. For the average use case the options listed in the quickstart are sufficient. Most options are related to operating system or filesystem related concepts so having a basic background in such things is recommended for more advanced configurations.
These option names and values are the same regardless of whether you
use them with the mergerfs command line program, in fstab, or in a
config file.
types
- BOOL = 'true' | 'false'
- INT = [MIN_INT,MAX_INT]
- UINT = [0,MAX_INT]
- SIZE = 'NNM'; NN = INT, M = 'B' | 'K' | 'M' | 'G' | 'T'
- PAGESIZE = UINT (representing number of pages) | SIZE (in bytes which will be converted to pages)
- STR = string (may refer to an enumerated value, see details of argument)
- FUNC = filesystem function
- CATEGORY = function category
- POLICY = mergerfs function policy
mount options
- config: Path to a config file. Same arguments as below in
keyorkey=valstyle format.#used for comments. - branches: Colon delimited list of branches. Used primarily in a config file.
- mountpoint=DIRPATH: The path to the mountpoint. Used primarily in a config file.
- branches-mount-timeout=UINT: Number of seconds to wait at startup for branches to be a mount other than the mountpoint's filesystem. (default: 0)
- branches-mount-timeout-fail=BOOL:
If set to
truethen ifbranches-mount-timeoutexpires it will exit rather than continuing. (default: false) - minfreespace=SIZE: The minimum available space of a branch necessary to be considered for a create policy. This is a default value applied to all branches and can be overwritten when configuring branches. Understands 'K', 'M', and 'G' to represent kilobyte, megabyte, and gigabyte respectively. (default: 4G)
- moveonenospc=BOOL|POLICY: When enabled if a write fails with ENOSPC (no space left on device) or EDQUOT (disk quota exceeded) the policy selected will run to find a new location for the file. An attempt to move the file to that branch will occur (keeping all metadata possible) and if successful the original is unlinked and the write retried. (default: pfrd)
- inodecalc=passthrough|path-hash|devino-hash|hybrid-hash: Selects the inode calculation algorithm. (default: hybrid-hash)
- dropcacheonclose=BOOL: When a file is requested to be closed
call
posix_fadviseon it first to instruct the kernel that we no longer need the data and it can drop its cache. Recommended when cache.files=partial|full|auto-full|per-process to limit double caching. (default: false) - direct-io-allow-mmap=BOOL: On newer kernels (>= 6.6) it is possible to disable file page caching while still allowing for shared mmap support. mergerfs will enable this feature if available but an option is provided to turn it off for testing and debugging purposes. (default: true)
- symlinkify=BOOL: When enabled and a file is not writable and its mtime or ctime is older than symlinkify_timeout files will be reported as symlinks to the original files. Please read more below before using. (default: false)
- symlinkify-timeout=UINT: Time to wait, in seconds, to activate the symlinkify behavior. (default: 3600)
- nullrw=BOOL: Turns reads and writes into no-ops. The request will succeed but do nothing. Useful for benchmarking mergerfs. (default: false)
- lazy-umount-mountpoint=BOOL: mergerfs will attempt to "lazy umount" the mountpoint before mounting itself. Useful when performing live upgrades of mergerfs. May not work on FreeBSD. (default: false)
- ignorepponrename=BOOL: Ignore path preserving on
rename. Typically rename and link act differently depending on the
policy of
create(read below). Enabling this will cause rename and link to always use the non-path preserving behavior. This means files, when renamed or linked, will stay on the same filesystem. (default: false) - export-support=BOOL: Sets a low-level FUSE feature intended to indicate the filesystem can support being exported via NFS. (default: true)
- kernel-permissions-check=BOOL:
Controls the FUSE
default_permissionsoption. Primarily for debugging. (default: true) - security-capability=BOOL: If false return ENOATTR when xattr security.capability is queried. (default: true)
- xattr=passthrough|noattr|nosys: Runtime control of xattrs. Default is to passthrough xattr requests. 'noattr' will short circuit as if nothing exists. 'nosys' will respond with ENOSYS as if xattrs are not supported or disabled. (default: passthrough)
- link-cow=BOOL: When enabled if a regular file is opened which has a link count > 1 it will copy the file to a temporary file and rename over the original. Breaking the link and providing a basic copy-on-write function similar to cow-shell. (default: false)
- statfs=base|full: Controls how statfs works. 'base' means it will always use all branches in statfs calculations. 'full' is in effect path preserving and only includes branches where the path exists. (default: base)
- statfs-ignore=none|ro|nc: 'ro' will cause statfs calculations to ignore available space for branches mounted or tagged as 'read-only' or 'no create'. 'nc' will ignore available space for branches tagged as 'no create'. (default: none)
- nfsopenhack=off|git|all: A workaround for exporting mergerfs over NFS where there are issues with creating files for write while setting the mode to read-only. (default: off)
- follow-symlinks=never|directory|regular|all: Turns symlinks into what they point to. (default: never)
- link-exdev=passthrough|rel-symlink|abs-base-symlink|abs-pool-symlink: When a link fails with EXDEV optionally create a symlink to the file instead.
- rename-exdev=passthrough|rel-symlink|abs-symlink: When a rename fails with EXDEV optionally move the file to a special directory and symlink to it.
- readahead=UINT: Set readahead (in kilobytes) for mergerfs and branches if greater than 0. (default: 0)
- splice=BOOL: Enable the kernel's splice syscall to move data between the FUSE device and the underlying filesystems without copying through user space. Read replies of 128KiB or larger are spliced; smaller read replies use the copy path. Writes stage their payload through a pipe at any size. Falls back automatically when unsupported. (default: true)
- pipe-max-size=SIZE: The value to write to /proc/sys/fs/pipe-max-size at mount time, needed only when fuse-msg-size exceeds the current limit while splice is enabled. Root-only; unprivileged mounts log and clamp instead. (default: 0)
- posix-acl=BOOL: Enable POSIX ACL support (if supported by kernel and underlying filesystem). (default: false)
- async-read=BOOL: Perform reads asynchronously. If disabled or unavailable the kernel will ensure there is at most one pending read request per file handle and will attempt to order requests by offset. (default: true)
- fuse-msg-size=PAGESIZE: Set the max number of pages per FUSE message. Only available on Linux >= 4.20 and ignored otherwise. (min: 1; max: 65535; default: "1M")
- read-thread-count=INT: Number of threads to
use. When used alone (
process-thread-count=-1) it sets the number of threads reading and processing FUSE messages. When used together it sets the number of threads reading from FUSE. When set to zero it will attempt to discover and use the number of logical cores. If the thread count is set negative it will look up the number of cores then divide by the absolute value. ie. threads=-2 on an 8 core machine will result in 8 / 2 = 4 threads. There will always be at least 1 thread. If set to -1 in combination withprocess-thread-countthen it will try to pick reasonable values based on CPU thread count. NOTE: higher number of threads increases parallelism but usually decreases throughput. (default: 0) - process-thread-count=INT: Enables separate thread
pool to asynchronously process FUSE requests. In this mode
read-thread-countrefers to the number of threads reading FUSE messages which are dispatched to process threads. -1 means disabled otherwise acts likeread-thread-count. (default: -1) - process-thread-queue-depth=UINT: Sets the number of requests any single process thread can have queued up at one time. Meaning the total memory usage of the queues is queue depth multiplied by the number of process threads plus read thread count. 0 sets the depth to the same as the process thread count. (default: 2)
- pin-threads=STR: Selects a strategy to pin threads to CPUs (default: unset)
- flush-on-close=never|always|opened-for-write: Flush data cache on file close. Mostly for when writeback is enabled or merging network filesystems. (default: opened-for-write)
- scheduling-priority=INT: Set mergerfs' scheduling
priority. Valid values range from -20 to 19. See
setpriorityman page for more details. (default: -10) - proxy-ioprio=BOOL: Use ioprio value from calling threads when reading and writing. (default: false)
- fsname=STR: Sets the name of the filesystem as seen in mount, df, etc. Defaults to a list of the source paths concatenated together with the longest common prefix removed.
- func.FUNC=POLICY: Sets the specific FUSE function's policy. See below for the list of value types. Example: func.getattr=newest
- func.readdir=seq|cosr|cor|cosr:INT|cor:INT:
Sets
readdirpolicy. INT value sets the number of threads to use for concurrency. (default: seq) - category.action=POLICY: Sets policy of all FUSE functions in the action category. (default: epall)
- category.create=POLICY: Sets policy of all FUSE functions in the create category. (default: pfrd)
- category.search=POLICY: Sets policy of all FUSE functions in the search category. (default: ff)
- cache.statfs=UINT: 'statfs' cache timeout in seconds. (default: 0)
- cache.attr=UINT: File attribute cache timeout in seconds. (default: 1)
- cache.entry=UINT: File name lookup cache timeout in seconds. (default: 1)
- cache.negative-entry=UINT: Negative file name lookup cache timeout in seconds. (default: 0)
- cache.files=off|partial|full|auto-full|per-process: File page caching mode (default: off)
- cache.files.process-names=LIST: A pipe | delimited list of
process comm
names to enable page caching for when
cache.files=per-process. (default: "rtorrent|qbittorrent-nox") - cache.writeback=BOOL: Enable kernel writeback caching (default: false)
- cache.symlinks=BOOL: Cache symlinks (if supported by kernel) (default: false)
- cache.readdir=BOOL: Cache readdir (if supported by kernel) (default: false)
- parallel-direct-writes=BOOL: Allow the kernel to dispatch
multiple, parallel (non-extending) write requests for files opened
with
cache.files=per-process(if the process is not inprocess-names) orcache.files=off. (Is a kernel feature added in v6.2) (default: true) - passthrough.io=ENUM: Enable FUSE IO passthrough if available. (default: off)
- passthrough.max-stack-depth=INT: Set to
1another filesystem can be stacked on mergerfs. Set to2to have mergerfs stacked over another filesystem. (default: 1) - never-forget-nodes=BOOL: Keep the internal representation of
a file after the OS tells mergerfs it is no longer needed, until the
node is unlinked, removed, or replaced. Really only needed for
exporting mergerfs via NFS. Formerly
noforget. (default: false) - allow-idmap=BOOL: Enables idmap (identity mapping). (default: true)
- debug: Enable debugging information. At the moment limited to a
FUSE message trace saved to
log.file. (default: false) - log.file: The file path for the FUSE message trace. Empty string will set to stderr. (default: stderr)
NOTE: Options are evaluated in the order listed so if the options are func.rmdir=rand,category.action=ff the action category setting will override the rmdir setting.
NOTE: Always look at the documentation for the version of mergerfs you're using. Not all features are available in older releases.