cow: subtree-aware whiteouts with a durable deletion log; type-aware copy-up#162
cow: subtree-aware whiteouts with a durable deletion log; type-aware copy-up#162congwang-mk wants to merge 7 commits into
Conversation
Signed-off-by: Cong Wang <cwang@multikernel.io>
…visibility and resurrection (#159) Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
…158) Signed-off-by: Cong Wang <cwang@multikernel.io>
…sions Signed-off-by: Cong Wang <cwang@multikernel.io>
…d of passing through (#158) Signed-off-by: Cong Wang <cwang@multikernel.io>
|
Thanks for taking on the whole deletion model — the subtree-aware whiteouts and the merged-view I re-ran each of the four as an in-cage test against this branch. A few things I would want resolved before it lands. Blocker — #158 is only half-closed; the hang is relocated to
Repro: lower FIFO Fix options: Should-fix — a directory rename onto an existing lower-only destination silently merges the two trees (new, reachable via #160).
Should-fix — #159 gap: the
Should-fix —
Nice-to-have —
Coupling with #148 — worth deciding the sequencing before either merges. These two rework the same
Suggested order: land Only the #158 commit hang is a hard blocker for me; the rest is should-fix/nice-to-have plus the sequencing call. |
|
Pushed the repros so you can run them directly: Three fail here — Two notes on how they are written: the FIFO one drives |
Redesign of the seccomp COW branch's deletion model. The flat exact-match
HashSet<String>(inherited from the Python-eracowfs/_branch.py, carried verbatim into the Rust rewrite) is replaced by a subtree-aware whiteout set, and copy-up becomes file-type-aware.Fixes #158
Fixes #159
Fixes #160
Fixes #161
The model
A new
DeletionSet(cow/deletions.rs) owns whiteout semantics:covers(rel)matches per path component: a whiteout ondhidesd/xandd/x/y, neverd2.rmdir d; mkdir dan opaque directory for free: the newdis visible, its old contents stay hidden.deleted.logbesideupper/and fdatasynced, so the deletion half of a change set is now self-describing on disk, like the upper already was. RAM stays the in-process source of truth; the log is the durability record a future recovery sweep (RFC RFC: Multi-sandbox transactions for pipelines #65 Phase 3, PR pipeline: transactional sequential pipelines over a shared COW workdir (RFC #65 Phase 1) #148's preserved branches) can replay.All merged-view queries (
is_deleted, open/stat/readlink,list_merged_dir,changes(),commit()) route through it, instead of each handler re-implementing its own slice of overlay semantics.Per issue
commit()to republish. Also fixes a latent bug of the same family found during the work:O_CREATon a whiteouted file used to resurrect the pre-delete lower bytes.> /dev/nullinside a learn-mode tree needs no real permission on/devand never touches the device) and removes the supervisor wedge.execute_copyadditionally guards withO_NONBLOCK+ fstat against the entry changing type between the classifying lstat and the open.The invariant
One test pins the property all four issues violated: the merged view the child observed during the run is exactly what
commit()publishes. Plus each issue's own reproducer as a unit test, and three end-to-end regressions driving a real sandboxed child (rm -r,mv dir,rmdirnon-empty).Compatibility
No public API, CLI, or SDK signature changes. Child-visible behavior changes only toward kernel semantics (ENOTEMPTY, ENOENT under deleted dirs, dir renames preserving contents). The branch storage dir gains
deleted.log; the layout is internal.Suites: 555 lib / 308 integration / 386 Python locally; the two
cli_testfailures on my machine (test_learn_captures_openat2,test_write_collapse_skips_protected) reproduce identically on main and are unrelated.