Skip to content

feat(fs): extent_sharing reports reflink/snapshot block sharing (0.1.21) - #353

Merged
zackees merged 1 commit into
mainfrom
feat/fs-extent-sharing
Sep 25, 2026
Merged

zackees merged 1 commit into
mainfrom
feat/fs-extent-sharing

Conversation

@zackees

@zackees zackees commented Sep 25, 2026

Copy link
Copy Markdown
Owner

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's bytes_reclaimed stops counting reflinked cache files.

Host Mechanism
Linux FS_IOC_FIEMAP, looking for FIEMAP_EXTENT_SHARED in any extent; volumes without FIEMAP fall back to the volume type (ext4/tmpfs/ramfs → Exclusive, otherwise Unknown)
macOS fstatfs f_fstypename: hfs/msdos/exfat → Exclusive, APFS and anything else → Unknown
Windows GetVolumeInformationByHandleW file system name: NTFS/FAT/FAT32/exFAT → Exclusive, ReFS and anything else → Unknown

The OS-specific code lives only in platform_{linux,macos,win}/fs_extent.rs; the neutral facade is in platform/fs/materialize.rs.

Tests

  • tests/fs/materialization.rs::extent_sharing_never_calls_a_reflinked_copy_exclusive: a fresh file is never Shared, a reflinked pair is never Exclusive, and a missing file returns NotFound.
  • Linux unit tests: the FIEMAP struct layout matches the kernel ABI, a tmpfs file is Exclusive, and a reflinked pair is exactly Shared.
  • Verified on real btrfs: the lib and fs test binaries were run in a privileged container with TMPDIR on a loop-mounted btrfs volume, and the reflink case printed reflink-shared-verified. Linux CI (ext4) can't reflink, so this path only runs where the volume supports it.
  • Clippy (-D warnings) is clean for x86_64-pc-windows-msvc, aarch64-apple-darwin and Linux, and the Python compatibility tests pass.

Labelled ci-full because this is platform-sensitive code.

🤖 Generated with Claude Code

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 zackees added the ci-full Run the complete release-equivalent CI matrix on this PR SHA label Sep 25, 2026
@zackees
zackees merged commit 536e781 into main Sep 25, 2026
14 of 19 checks passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-full Run the complete release-equivalent CI matrix on this PR SHA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant