feat(fs): extent_sharing reports reflink/snapshot block sharing (0.1.21) - #353
Merged
Merged
Conversation
A hard-link count cannot prove that deleting a file frees its space: reflinks and snapshots share blocks between files that each have one link (zackees/zccache#1673, where a retired-store sweep over-credited reclaimed bytes after reflink restores into target/). extent_sharing returns Exclusive, Shared, or Unknown. Linux reads the file's FIEMAP extent map and looks for FIEMAP_EXTENT_SHARED, falling back to the volume type (ext4/tmpfs/ramfs cannot share) when FIEMAP is unsupported. macOS and Windows answer from the volume's file system: HFS+/FAT/exFAT/NTFS are Exclusive, APFS and ReFS are Unknown. Verified on a loop-mounted btrfs volume: a reflinked pair reports Shared. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zackees
added a commit
to zackees/zccache
that referenced
this pull request
Sep 26, 2026
kernal-api 0.1.21 (zackees/kernal-api#353) publishes the platform::fs::extent_sharing facade the retired-store sweep uses to credit only unshared blocks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zackees
added a commit
to zackees/zccache
that referenced
this pull request
Sep 26, 2026
kernal-api 0.1.21 (zackees/kernal-api#353) publishes the platform::fs::extent_sharing facade the retired-store sweep uses to credit only unshared blocks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zackees
added a commit
to zackees/zccache
that referenced
this pull request
Sep 26, 2026
…reflink-aware byte credit (#1673) (#1676) * fix(daemon): age-gate retired-store sweep and never sweep newer stores (#1673) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(daemon): backdate retired-store victims past the #1673 grace period Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * style: rustfmt retired-store changes (#1673) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(core): credit retired-store bytes only for unshared blocks (#1673) A reflink restore into target/ (ReFS, btrfs, XFS, APFS) leaves the cache file at nlink == 1 while sharing every block, so the link count alone over-credited bytes_reclaimed and over-estimated the pressure decision's reclaimable retired bytes. file_frees_space_on_removal now also requires kernal_api::platform::fs::extent_sharing to report Exclusive; unknown sharing never counts. Verified RED -> GREEN on a loop-mounted btrfs volume: the old rule credited 262144 bytes for a reflinked entry, the fix credits 0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * style: rustfmt retired_store re-exports (#1673) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * build(deps): pin kernal-api =0.1.21 for fs::extent_sharing (#1673) kernal-api 0.1.21 (zackees/kernal-api#353) publishes the platform::fs::extent_sharing facade the retired-store sweep uses to credit only unshared blocks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(daemon): keep the #1659 pressure estimate alive on APFS/ReFS (#1673) extent_sharing reports Unknown on every APFS and ReFS volume, so requiring Exclusive in retired_store_bytes zeroed the pressure estimate on macOS and silently disabled the retired-store pressure valve there (macOS CI: issue_1659_retired_store_bytes_are_reclaimed_before_live_entries). Split the two rules: bytes_reclaimed (reported) still credits only a last link with proven-exclusive blocks, while the pressure estimate counts any last link not proven shared (file_may_free_space_on_removal), excluding only btrfs/XFS reflinks. The core sweep test now expects credit only where the temp volume proves exclusivity. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(daemon): expect retired-byte credit only on exclusivity-proving volumes (#1673) On APFS/ReFS extent_sharing reports Unknown, so the pressure sweep removes retired files but credits no reclaimed bytes (macOS CI failure at disk_maintenance_unit.rs:1196). The re-plan already uses the recomputed estimate and fresh free space, so no live entry is evicted there; only the test's credit expectation was platform-blind. Also rustfmt the re-exports. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <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.
Summary
Adds
kernal_api::platform::fs::extent_sharing(path) -> io::Result<ExtentSharing>(Exclusive/Shared/Unknown), and bumps the version to 0.1.21.A hard-link count can't prove that deleting a file frees its space: reflinks and snapshots share blocks between files that each have
nlink == 1. zackees/zccache#1673 needs this so the retired-store sweep'sbytes_reclaimedstops counting reflinked cache files.FS_IOC_FIEMAP, looking forFIEMAP_EXTENT_SHAREDin any extent; volumes without FIEMAP fall back to the volume type (ext4/tmpfs/ramfs →Exclusive, otherwiseUnknown)fstatfsf_fstypename: hfs/msdos/exfat →Exclusive, APFS and anything else →UnknownGetVolumeInformationByHandleWfile system name: NTFS/FAT/FAT32/exFAT →Exclusive, ReFS and anything else →UnknownThe OS-specific code lives only in
platform_{linux,macos,win}/fs_extent.rs; the neutral facade is inplatform/fs/materialize.rs.Tests
tests/fs/materialization.rs::extent_sharing_never_calls_a_reflinked_copy_exclusive: a fresh file is neverShared, a reflinked pair is neverExclusive, and a missing file returnsNotFound.Exclusive, and a reflinked pair is exactlyShared.fstest binaries were run in a privileged container withTMPDIRon a loop-mounted btrfs volume, and the reflink case printedreflink-shared-verified. Linux CI (ext4) can't reflink, so this path only runs where the volume supports it.-D warnings) is clean forx86_64-pc-windows-msvc,aarch64-apple-darwinand Linux, and the Python compatibility tests pass.Labelled
ci-fullbecause this is platform-sensitive code.🤖 Generated with Claude Code