Repository navigation
fix(daemon): integrate stalled unmount recovery with exact abort custody (#496) - #500
Merged
Merged
Conversation
…write (#426, #460) A normal unmount can detach successfully and still stop at Join: when another mount of the same superblock outlives the detach, the kernel never ends the connection, its receive loops stay blocked, and the entry was kept as Retained at Join with no way out but a forced unmount — or, where no abort control is bound, no way out at all (#426, #460). The unmount now makes the same single abort write a forced unmount makes, on the already-detached connection, and drains again. It then completes as Unmounted, revokes and closes, so the stalled connection ends where the unmount asked. Only a refused or short write, or a second stop, keeps the custody, exactly as any other stop does; such an entry is not forceable either, because its abort control has been used. - layerfs-fuse: Undrained::end_stalled, one abort_detached write then force_drain, only for a Join stop. - layerfs-daemon: unmount_kernel calls it on a Join stop; a second stop keeps the evidence as before. - tests: stalled_unmount now asserts the normal unmount ends the stall itself (the copy of the mount answers ENOENT) and keeps no custody. - docs: native mount session and forced teardown describe the automatic abort; the SDK skill and the unmount comment no longer send callers to --force for this case. Tests: - cargo test -p layerfs-daemon --test stalled_unmount --release in a privileged Linux container: passes; the parent's code keeps custody, so the test fails without this change. - also ran mounted_drain, fp21_detach_stages, control_root, mounted_fusectl, forced_unmount and forced_unavailable; all pass except the environment bound fp31 reclaim observation in mounted_drain (container cgroup memory reclaim, unrelated to unmount). Production LOC: 102763 -> 102777 (delta +14) core 38395 -> 38395 (0), engine 61709 -> 61723 (+14), api 2659 (0).
Record the attempted abort in the FUSE failure receipt. Report failed and short writes at Abort with the original errno/count, and carry abort effects through second-drain, Revoke and Close failures. Successful normal unmounts still reply Unmounted, with no new syscall, replay or ownership release. Add five Linux mounted regressions alongside the success case using external thread-local seccomp and public owner APIs. Parent: failed/short abort tests fail with Join/forced=None. Fixed: all six pass; existing forced_unmount (3), forced_unavailable (1), fp21_detach_stages (2), and FUSE/Bridge tests (33) pass. All-target Clippy for daemon/FUSE/Bridge denies warnings; fmt, product and fuser guards pass. Tooling: 155 tests plus six after CI inventory adjustment. Tests built first; execution capped at 100 s (mount), 90 s (FUSE/Bridge), 120 s (tooling). Disposable only. No full SDK E2E or benchmark claim. The final strengthened success assertion passes and its Clippy check passes. Ruff 0.17.2 formatting passes; optional lint retains existing EXE001 on the non-executable ci_tests.py shebang. No third-party changes. Deleted tests: none. Production LOC: 102777 -> 102816 (delta +39) First-parent comparison: 3a0564b (tree 799fab1) -> staged tree 7f0d78d. Scopes: core 38395 -> 38395 (0); engine 61723 -> 61762 (+39); api 2659 -> 2659 (0). Method: tools/production_loc.py blob 3341e4d, --root <exact exported tree> --json for each snapshot. First-party production Rust, runtime SQL and JavaScript; tests, docs, tooling, generated and third-party code excluded. Reference absent (retired R9c; last counted 65,417 at tree 498dd19). Evidence and limitations: core/docs/issues/496/ABORT-CUSTODY-FIX-20261029.md.
mengmengmengqiang
added a commit
to tokenaissance/layerfs
that referenced
this pull request
Oct 28, 2026
jiangkoumo
added a commit
to jiangkoumo/layerfs
that referenced
this pull request
Oct 29, 2026
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.
Integrates #496 and fixes its retained abort evidence before merging. A normal unmount that stalls at Join still makes one abort write and drains again; unsuccessful teardown now preserves the actual abort disposition and original errno/count through the second drain, Revoke and Close. Successful normal unmounts still return
Unmounted.The branch contains #496's original commit plus
69fedcacf0. GitHub rejected the maintainer push to the author's fork, so this upstream branch carries the reviewed correction without rewriting the author's history. Merge with a merge commit so #496's original head remains in main's ancestry.Validation on Linux ARM64 with Rust 1.85.1, locked dependencies and repository flags:
Failure tests use thread-local seccomp on the test's own abort descriptor, including an externally simulated acknowledged write to exercise the second drain stop. The Revoke/Close fixtures use public owner APIs. No production test hooks, new dependencies or wire format changes. No deleted tests.
Combined merge tree
ddea2b5453ec2294a3a3096ff1341d29467c9ff5against main9af53da046: all six stalled-unmount cases and all eight SDK unmount-dirty tests pass.Details, failed fixture diagnosis and evidence locations: fix record.
Production LOC, corrective commit: 102777 -> 102816 (delta +39): core 0, engine +39, API 0.
Prepared first-parent merge comparison against main
9af53da0468c2ea7b3a273a4a7037afc059ff27b: 102778 -> 102831 (delta +53); core 38395 unchanged, engine 61724 -> 61777, API 2659 unchanged. Counter: tools/production_loc.py blob3341e4d0362c822b6d9a08419c432942b3a13800,--root <exact exported tree> --json, excluding tests/docs/tools/generated/third-party code. Reference absent (retired R9c; last counted 65,417 at tree 498dd1917812).