- Add a top-level Migration page covering both migration directions.
- Explain filesystem reuse, parity constraints, partition requirements,
and unlocking encrypted Unraid disks.
- Describe intact ZFS pool imports and subdirectory branch reuse,
distinguishing them from cases requiring a data copy.
- Add navigation and link the guide from the Unraid comparison.
* Add: a comprehensive downsides FAQ with mitigations and practical
priorities.
* Document: mergerfs-webui and link it from setup and configuration
guides.
* Replace: obsolete mergerfs.fsck references with fsck.mergerfs
guidance.
Describe why mergerfs does not aggregate branch performance like
RAID/ZFS (whose aggregate throughput is also capped by shared
interconnects) and instead provides independent per-branch
performance: best case A+B+C across concurrent streams, worst case
single-stream limited to one branch's speed.
- Store cloned read-worker fds on fuse_session and close them there.
- Set up clone fallback through session helpers used by the loop.
- Carry per-request fds through receive, process, and reply paths.
Tests show significant performance increases in highly concurrent
workloads on a high core count system. Upto 15% better on reads and
27% on writes.
- Expose the ioprio enabled flag as an atomic for relaxed inline checks
- Inline SetFrom construction so disabled read/write paths avoid a function call
- Move priority application into a slow helper used only when ioprio is enabled
- Guard fuse_cfg_t log file and filepath shared pointers with a shared mutex
- Replace atomic shared pointer loads and stores with shared and unique locks
- Replace atomic shared pointer loads/stores with shared/unique locking.
- Store the configured readdir mode directly as std::string.
- Copy the active ReadDir implementation under lock before invoking it.
- Use relaxed increment under the map bucket lock when duplicating file handles.
- Use acq_rel decrement when releasing and checking for final references.
- Load moved ref_count with relaxed ordering during map insertion.
- Explain that the mutex is per readdir call.
- Document that only dirent deduplication and list append are serialized.
- Clarify that per-branch opendir and getdents64 work runs outside the critical section.
- Replace the per-file Mutex with std::shared_mutex for shared write access.
- Run direct and cached writes under a shared lock while the fd is stable.
- Retry failed writes under a unique lock before move-on-ENOSPC relocation.
- Add helpers that release path locks and update node state under f.lock.
- Update getattr and setattr stat-cache invalidation while preserving ESTALE handling.
- Rework create, open, tmpfile, and set_path_info to mutate lookup/open state under the shared lock.
- Document the lock/unlock pair as an acquire/release barrier.
- Explain that releasedir waits for in-flight readdir calls before destroy/free.
- Warn against removing the synchronization despite it not being a critical section.
Important changes:
- Switch mergerfs and vendored libfuse Makefiles to -std=c++20.
- Select the latest available GCC/G++ or toolset in container builds.
- Verify compiler C++20 support during package installation.
- Fix dynamic SysLog formatting for fmt C++20 checks.
- Add mergerfs_mount() context manager in posix_parity.py that creates
temporary branch dirs in tests/.test_tmp/, mounts an ephemeral mergerfs
instance, and cleans up after use.
- Add find_mergerfs(), find_fusermount(), mount_mergerfs(), unmount_mergerfs()
helpers.
- Update run-tests to invoke each TEST_* script without a mountpoint arg.
- Update README.md to document the new `python3 tests/run-tests` invocation.
- Fix 44 tests to use mergerfs_mount() instead of expecting a pre-mounted path.
- Add tempfile import to 10 tests that were missing it.
- Fix TEST_mount_lifecycle to use mergerfs_mount() context manager.
- Fix TEST_posix_tmpfile missing join import.
- Fix TEST_cfg_xattr_modes error message framing (no "(known bug)").
- Fix TEST_posix_copy_file_range: loop-copy full size, compare st_size and
SHA256 hash; add NativeTmp for space management; route native temp to
tests/.test_tmp/ to avoid ENOSPC on /tmp.
- Fix TEST_posix_getattr_fgetattr: st_cmp skips st_size for dirs; add
compare_ino param for safe inode comparison when inodecalc=passthrough.
- Fix TEST_unlink_rename, TEST_use_* tests: namespace cleanup, consistent
variable naming, None check for cmpfunc.
- Fix TEST_readlink_semantics: remove type annotations to support older
Python; wrap in mergerfs_mount() try/except.
- Add flush=True to run-tests print so test names show immediately.
- Fix typo in static.installer: /pkg/ -> /pkgs/
- Add missing mkdir -p /build before makeself
- Mount pkgs directory via podman build -v so static.installer can access
previously built static tarballs without relying on bind mounts relative
to the build context
- Register qemu-user-static binfmt handlers for cross-compilation
- Make --git-repo optional when using --setup
- Reserve a zero stat CRC to represent an invalid cache fingerprint.
- Include device, size, inode, mtime, and ctime data in the fingerprint.
- Recompute the fingerprint during auto-cache open before keeping cache.
- Make the test runner fail on failed tests and report explicit skips
- Strengthen assertions for O_DIRECT, LUP policy, EXDEV fallback, and xattrs
- Fix cleanup and file descriptor handling across test scripts
No functional change: libfuse/helper.cpp (fuse_daemonize,
fuse_helper_opt_proc, fuse_parse_cmdline) and mergerfs
fuse_init.cpp (_want helpers) reformatted to match the project's
GNU-style brace placement and aligned parameter lists.
- fuse_opt: reformat process_opt_param to project style; return the
rv from sscanf through a named local so the error branch prints
the failing option cleanly.
- cpu.cpp: when parsing /sys/devices/system/cpu/*/topology/core_id,
bail out cleanly on stream read failure rather than recording an
uninitialized core_id.
- fusermount: free(copy) on the success path of parsing the mount
option (previously leaked on every mount), and replace the fixed-
buffer sprintf into procfile with snprintf bounded by the buffer
size.
- maintenance_thread: widen the iteration count from int to u64
so a long-lived daemon doesn't wrap after ~68 years of ticks
(real effect: silence signed-overflow warnings under UBSan).