Repository navigation
pool: one rule per live volume invariant, whole-repo audit - #398
Merged
Merged
Conversation
Drop the live-writer replica policy (three errors, a 503 retry contract and a checkpoint-reference probe): a claim holding volumes is already never replicated, publication rechecks holds, and the scheduler retires the replica on its next pass. Release and live detach now share the engine's clean-unmount rule, so a writable superblock remounted read-only keeps the dirty marker on release too. Drop the temporary writer hold around the live marker unlink; it guarded a detach stalled between its final check and an unlink across a whole release and new writer admission.
Inline the live-addition hold helper back into stageVolumeTarget now that it carries no replica check, return SetVolumes' target as is since ValidateVolumes copies it, and name the shared unmount helper for both of its callers.
On current guest kernels an ext4 error with errors=remount-ro leaves the superblock options at rw,emergency_ro instead of ro, so release and live detach cleared the dirty marker of a filesystem that had failed. Found on cocoon-test2 with trigger_fs_error.
…ker hold The marshal test fed invalid UTF-8 that the HTTP decoder already rejects, and the marker-unlink test came with the temporary writer hold this branch removes; a failed unlink only keeps the marker.
Release reused live detach's device lookup and post-unmount rescan, six guest calls per writable mount, and cost cocoon-test2 +19 ms p50 per writable release. Release only needs the clean verdict, so it reads mountinfo once, takes the device from the mount entry, and checks options, superblock and other mounts of that device with the predicate live detach shares.
This was referenced 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.
Whole-repo audit after #380–#397, with the live volume design points from the #382/#383 reviews settled.
Removed
ErrReplicaPresent(503 +Retry-After),ErrReplicatingPool,ErrReplicaStranded,liveWriterErrorLockedat two call sites,claimStore.hasCheckpointReferences, and the two log exceptions for them. The existing rule already covers the case: a claim holding volumes is never replicated, publication rechecks holds (replicateandputRow), and the scheduler retires the replica on its next pass (TestReplicaClaimThatGainsVolumesStopsBeingReplicated). A read-only live addition already took that path; refusing only writers had no basis.Unified
cleanMount: whole filesystem, writable mount and superblock options, no other mount of the device) for live detach and release. Release reads mountinfo once, takes the device from the mount entry and unmounts (two guest calls); live detach keeps its device lookup because it must refuse unplugging a device mounted elsewhere. Before, release cleared the marker after any successfulumount. Tests:TestReleaseKeepsMarkerAfterUncleanUnmount,TestUnmountVolumeReportsCleanWritableUnmount.errors=remount-ro, current guest kernels report the superblock asrw,emergency_ro, notro, so both release and live detach cleared the marker of a failed filesystem.emergency_ronow counts as read-only.Simplified
stageVolumeTarget(its pre-pool: allow live writable and attach-only volumes #383 shape);SetVolumesno longer copies a target thatValidateVolumescopies anyway.Kept, with reasons
attach_only: the wire needs it for GET-to-PUT, andclaimDTOsharestypes.Volume; a separate type costs more than the 5-line load migration.putRow's holds guard: it is the one place every replica row publish passes, soreputArchivecannot republish a volume-bearing row.Hot path: claims and releases without writable mounts are unchanged (A/B on the dev box: no-volume release 15.48 vs 15.45 ns, volume admit+release 3.584 vs 3.598 µs, p > 0.4). A release with writable mounts makes two guest calls instead of one.
Hardware (cocoon-test2 and cocoon-test1, cocoon v0.7.4 isolated roots, rt:24.04 sha256:03e8bed49d4c, main 5e9cded vs this branch, arms interleaved):
sandboxd-e2e.shwith the read-only, writable and live volume legs passes on every arm on both hosts (23.9–24.4 s on test2).trigger_fs_erroron a writable volume (superblockrw,emergency_ro): main clears the dirty marker on release and on live removal on both hosts; this branch keeps it in both paths on both hosts.Audit scope: the 33 production files the hygiene ledger listed as changed since their last clean read, plus #396.
store/s3andmetastore(#384), silkdpty.rs/sysutil.rs(AsyncFd), and #396 (no_rx_splice) needed no change; comments added since the last read are all one-line docs on exported items orSAFETYlines.Net: prod −24, test −100, docs −5.
Gates: golangci-lint v2.13.2
0 issues.×10 (5 modules, linux and darwin), fmt clean,go test -racein every Go module, 257 Python tests, asl shows only the five forwarders main already has.