Commit graph

514 commits

Author SHA1 Message Date
Antonio S. Musumeci
e67b7d0825 log: default debug log path to empty; skip set when empty
libfuse previously initialized its debug log filepath to
"/dev/stderr", forcing the config layer to reopen stderr on every
load whether or not the user asked for it. Default the libfuse log
path to "" and have the mergerfs config layer only forward the
request to libfuse when the user supplied an explicit path.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
981d5473ee str: null-safe same() and startswith()
Both helpers previously called strcmp/pointer-dereference directly
on their arguments, so a stray NULL (e.g. an unset env string or an
absent xattr) crashed the process. Guard both helpers: same()
returns true only if both pointers are equal, startswith() returns
false if either side is NULL.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
364f8c4407 fs_movefile_and_open: -ENOSPC when no destination branch available
The create policy can legitimately return success with an empty
destination list (e.g. every candidate rejected). Previously we
then dereferenced dst_branch[0] and faulted. Return -ENOSPC so the
original write that triggered the move propagates a sensible errno
to userspace.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
ef9c7ad5df fuse_statfs: scale with long double to avoid integer overflow
The branch-aggregation code computed
  blocks * f_frsize / min_frsize
as u64 arithmetic. With large filesystems the intermediate product
blocks * f_frsize overflows 64 bits long before the division can
bring the result back into range, producing garbage bavail/bfree
values reported to userspace.

Compute the scale factor once in long double and multiply each
count by it, so the only narrowing happens in the final cast back
to fsblkcnt_t.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
4288a60c5d fuse_readlink: always null-terminate buffer
Old code only null-terminated when the returned/copied length was
strictly less than the caller-supplied bufsize_, leaving the buffer
unterminated on an exact-fill. Since buf_ is consumed as a C string,
reserve one byte for the terminator up front and unconditionally
terminate.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
cf38a37176 fuse_readdir: atomic initialized flag; bound error string; check msgbuf allocation
- ReadDir::_initialized is set by the first thread through the
  lazy-init path and read by every subsequent caller; make it
  std::atomic<bool> so the read/write pair has a happens-before
  relationship.

- The 'no valid mergerfs branch found' error directory entry used
  strcpy into a fixed-size dirent buffer. The message happens to
  fit today but the buffer is only NAME_MAX wide; switch to a
  length-bounded strncpy driven by the constexpr string size.

- The getdents implementations for seq/cor/cosr allocated a msgbuf
  without checking for allocation failure and then dereferenced it.
  Return -ENOMEM when the allocation fails.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
f5d9a60b9d fuse_getattr/statx: populate timeouts in fake_root and controlfile replies
The fake-root and control-file fast paths returned a synthetic stat
without touching the timeout struct. Callers that took those paths
ended up sending whatever the timeout struct happened to hold,
which is uninitialized memory for the control-file path and
whatever a prior call left there for the fake-root path. Kernel
behavior is undefined when the timeout is garbage.

Pass timeout_ into both helpers and set entry/attr from the
configured cache values.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
0c17492c78 FUSE: pass Branches::Ptr by value with empty-branches guards
Previously most FUSE ops took a reference to the live cfg.branches
object. With atomic_load now producing a shared_ptr snapshot, pass
it by value: the op works against a single stable view of the
configuration for its whole lifetime, immune to concurrent
reconfiguration.

Also bail out with -ENOENT when the policy returns an empty branch
set rather than dereferencing branches[0]. This was reachable if a
policy rejected every branch (e.g. everything readonly while
looking for a writable target).

Covers access, chmod, chown, create, getattr, getxattr, ioctl,
link, listxattr, mkdir, mknod, open, readdir (cor/cosr),
readlink, removexattr, rename, rmdir, setxattr, statfs, statx,
symlink, truncate, unlink, utimens.

While here, in _getattr only dereference st_->st_mode when lstat
succeeded (it is otherwise uninitialized).
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
98648ae44b FUSE: require valid file/dir handle; drop open_files fallback
Several FUSE ops fell back to looking up a FileInfo via
state.open_files when the kernel-provided fh was zero, returning
-ENOENT if the lookup failed. This path papered over handle-tracking
bugs and added cost on every call. Use the handle directly and
return -EBADF when it is invalid - the kernel should always hand us
a valid fh for an open resource.

Also simplify FileInfo::from_fh / DirInfo::from_fh and their to_fh
helpers: callers now handle the null-pointer case explicitly so the
ASSERT_NOT_NULL checks are redundant.

Covers fallocate, fchmod, fchown, fgetattr, flock, ftruncate,
futimens, read, release, releasedir, write, statx, ioctl (file +
dir), readdir (sequential, concurrent-on-read,
concurrent-on-search), and the passthrough fast paths in
create/open.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
0dcca0f1a3 branches: re-link default_minfreespace pointer on copy/move; atomically publish branch mode changes
Branches using the default minfreespace held a reference to their
owning Impl's _default_minfreespace. After a copy or move the
pointer still referenced the source Impl, which could become
invalid or diverge after further configuration changes. Switch to
a pointer and re-link it to the destination Impl on copy/move.

While here, convert set_branch_mode to do an atomic_store of a
newly constructed Impl rather than mutating the shared pointer
target in place. Readers holding an atomic_load snapshot are no
longer affected by a concurrent mode change.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
103cd358f2 state: atomic ref_count in OpenFile
ref_count is read and written from multiple FUSE worker threads
during open/release. Make it std::atomic<int> and provide a move
constructor so OpenFile remains movable when the underlying atomic
is non-movable.
2026-04-18 13:47:23 -05:00
Antonio S. Musumeci
aa46001923 Remove unused rwlock.hpp header and includes
rwlock.hpp was left over after migrating to atomic shared pointers
for branches configuration. No code references ReadGuard/WriteGuard
any longer, so drop the header and its stale includes.
2026-04-18 13:47:23 -05:00
Antonio SJ Musumeci
ff48ff6047 Handle/ignore SIGHUP
Some checks are pending
mkdocs / deploy (push) Waiting to run
2026-04-17 11:14:05 -05:00
Antonio S. Musumeci
a1e681f36b Use ReaddirCalc in all readdir implementations
* avoids per-entry path construction
2026-04-12 23:44:23 -05:00
Antonio S. Musumeci
e3a467de80 Refactor fs_inode
* add Algo enum
* ReaddirCalc class
* string_view params
* fs::path overloads
2026-04-12 23:44:23 -05:00
Antonio S. Musumeci
cdadda5eb9 Replace khash with custom hash set 2026-04-12 23:44:23 -05:00
Antonio SJ Musumeci
425e30b50f Use nanosleep rather than yield and return EINTR
Some checks failed
mkdocs / deploy (push) Has been cancelled
2026-04-11 11:30:57 -05:00
Antonio SJ Musumeci
6d218fa87f Misc updates and fixes
Some checks failed
mkdocs / deploy (push) Has been cancelled
2026-04-04 02:46:24 -05:00
Antonio SJ Musumeci
1ebc8cfa5f Enable statx with file handle
Some checks are pending
mkdocs / deploy (push) Waiting to run
2026-03-31 19:53:17 -04:00
Antonio SJ Musumeci
acfa797503 Misc formatting changes 2026-03-31 19:53:17 -04:00
Antonio SJ Musumeci
7fc20457ca Rework open file resource management 2026-03-31 19:53:17 -04:00
Antonio SJ Musumeci
0f1a8e9b69 Fix error condition in fs_copyfile 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
08f9cc6932 Fix readlink implementation, add more tests 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
3099b15db1 More aggressive error handing with pagesize queries 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
7763c7384a Use fatal::abort() rather than assert in places 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
61365d226d Move scope_guard to vendored/ 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
f33e78bc24 Cleanup procfs and abort on critical issues 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
7f52623536 Cleanup branches and add more unit tests 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
a30a4df9c0 Cleanup config and add tests 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
1e0d5aa91d fs_wait_for_mount cleanup 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
d09fadbc28 fs_inode cleanup 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
21ce889449 Fixup listxattr error handling 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
9d1a4696e9 Small improvements to fs::statvfs_cache 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
ed0cbcf064 Cleanup fuse_readlink 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
bf98d3f3a6 Fix possible error handling issue with errno 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
c45c5ce920 Make cfgfile depth calculation thread friendly 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
e0a892f0d0 Improve error handling when querying pagesize 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
3a45be4cd8 Rework string utils, more test cases 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
107a3acf95 Better error handling in pagesize config type 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
a5eafb8972 Check string is not empty before resize in Config::keys 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
8199cc8a8b Fix error handling in fuse chmod, chown, setxattr, removexattr 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
c0af09f7d8 Fix incorrect type in fs_read and write 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
1a5c39f813 Fix buffer overflow in readlink by reserving space for null terminator 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
fce1803d42 Use RND class for shrink_to_rand_elem and add assertions 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
8648de6bb6 fix policy_eppfrd.cpp: return 0 when branchinfo found, -ENOENT only when empty 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
f227a63e15 fix str.cpp: use string_view::npos, fix erase() calls, remove extra whitespace 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
aa47b74dea Remove iterator methods from Branches class 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
206ad1dd53 Fix futimens bugs: stat pointer, variable names, and negation 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
80aead7085 Add null pointer checks for FileInfo/DirInfo 2026-03-24 21:13:34 -04:00
Antonio SJ Musumeci
1220befacf Fix copydata_copy_file_range bug 2026-03-24 21:13:34 -04:00