xfs: identify filesystem without root, and fail loud when it can't - #85
Merged
Conversation
On XFS (any non-btrfs fs) oans looked up the filesystem UUID via libblkid, which needs root or a populated blkid cache. Run unprivileged on a fresh device, the lookup failed, the scan root was silently rejected, and oans reported "Nothing to deduplicate" and exited 0 — looking like success while doing nothing. - Try FS_IOC_GETFSUUID first (Linux 6.4+): an unprivileged fd ioctl that returns the fs UUID directly, no root and no blkid cache needed. Falls back to the mountinfo + libblkid path on older kernels (ENOTTY). btrfs already had an unprivileged ioctl path and is unchanged. - If no root can be locked onto a supported filesystem, stop with a clear error and non-zero exit instead of a silent no-op. - CI: add an XFS leg (matrix over btrfs/xfs) that runs the integration suite unprivileged, proving the FS_IOC_GETFSUUID path end to end. - Document the XFS/root requirement in the README and man page. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address the /simplify pass on the XFS robustness change: - copy the FS_IOC_GETFSUUID bytes with uuid_copy() to match the file's idiom (used at the other UUID copy sites) instead of a hand-rolled memcpy. - collapse the triplicated "if (!parent_checked) seed_fs_lock_failed = true;" rejection at the three fs-lock failure exits in check_file into a single seed_reject() helper, removing the duplication and the added nesting. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
test_shared_tail_is_deduped builds a partially-shared file by writing a head, fsync, then the shared tail to force an extent boundary so the tail is its own extent for the extent pass to match. That boundary only forms under copy-on-write: XFS overwrites in place and keeps the file as a single extent, so the tail is never a matchable extent and the dedupe cannot happen there. This is the same btrfs-COW dependency the sibling test_least_fragmented_target.py already gates on with @requires_btrfs; this test was mislabeled @requires_reflink and only surfaced now that CI runs an XFS leg. Genuine whole-file and naturally-aligned dedupe still works on XFS (proven by the other integration tests, which pass on the XFS leg). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Running oans on XFS unprivileged silently scanned 0 files and exited 0 (
Nothing to deduplicate) — looking like success while doing nothing. Root cause: for any non-btrfs filesystem, oans reads the fs UUID via libblkid, which needs root or a populated blkid cache. On a fresh device run without root, the lookup fails → the scan root is rejected → the whole tree is discarded. (btrfs is unaffected: it reads the UUID via an unprivileged ioctl.)Discovered while confirming the "works on btrfs and XFS" claim for launch: a real XFS reflink smoke test deduped correctly as root, but the unprivileged run exposed this.
Changes
FS_IOC_GETFSUUID(Linux 6.4+): an fd ioctl that returns the fs UUID directly — no root, no blkid cache. Falls back to the existing mountinfo + libblkid path on older kernels (ENOTTY). This makes XFS work unprivileged on modern kernels.FS_IOC_GETFSUUIDpath end to end. The harness auto-skips the few btrfs-only (fragmentation) tests on XFS.Testing
scripts/verify.sh: 88 integration tests pass, valgrind clean.FS_IOC_GETFSUUIDsucceeds unprivileged locally (a tmpfs dir that the old blkid path could not identify is now scanned without a UUID warning).Reclaimed 38.1 MiB).🤖 Generated with Claude Code