Repository navigation
pool: allow live writable and attach-only volumes - #383
Conversation
dc7a4e3 to
e9c236d
Compare
|
These changes look right in direction:
Two notes for when this is rebased on the slimmed #382:
|
7167a2f to
8d963fd
Compare
8d963fd to
96f9abd
Compare
|
Thanks for the catalog follow-ups in #395. I've added 8661848 on top of 96f9abd to fix a marker race found during the next review. An old live detach could pass its final check, then pause before removing The clear now takes one temporary writer reference under the same lock as the final check and returns it when the file operation finishes. Release, reap and ownership-transfer cleanup release their own references. File I/O stays outside the manager lock. This adds no journal state or fsync and leaves the empty-volume release path unchanged. On 8661848, 14 deterministic schedules passed 20 times each under I also compared 96f9abd with 8661848 in eight alternating runs per side, using Go 1.27.1,
Each side completed 4,800 Manager cycles without errors, checking marker creation and removal on every cycle. Claim fsync used the default off setting; marker directory sync still ran. The extra bookkeeping costs about 67 ns with no heap allocation. The complete cycle's difference is within run variation. Separate CPU profiles show file operations dominate that cycle. These measurements use a fake VM engine and do not measure VM latency or saturated lock contention. |
Extend live mutations and SDKs with explicit per-volume attachment modes. Keep dirty-marker cleanup tied to engine proof and reject writer admission while replica recovery remains possible, using the catalog and main claim ordering without a volume-reference ledger.
Remove the recovery-only reference description after the volume ledger was deleted. Pending or detaching entries still require an explicit caller retry when no request is active.
Acquire an operation reference with the final run check so concurrent claim teardown cannot admit a new writer before the old host unlink finishes. Keep that reference local and release it on both success and unlink failure.
One-line DetachVolume and WithVolumesAttachOnly docs, keyed volumeMount fields, a named admission helper instead of an inline closure, no slice copy for claims without the legacy attach-only flag, attach_only named in shape-change errors, and two doc lines aligned with the code.
Remove the e2e marker test that repeated the pool test and its fake mount tracking, fold the empty-source mountinfo case into the engine table and keep one malformed row, restore read-only mounts in the cancel and gate tests, pass subtest t into replica table closures, and fold single-row and repeated Python cases.
8661848 to
d0612c6
Compare
#383 refuses publishing a replica row while volume holds exist, so archived claims no longer need to count volumes; the adoption, restart, transfer and reap bookkeeping and the legacy-row tests go. Compat removals (claim-wide volumes_attach_only, journal attach_only migration, per-call cocoon v0.7.2 gate) are scheduled for a later release.
This is the live-volume follow-up to #382 in the #300 series, following the split agreed in #379. It depends on #382 and stays draft until that PR merges. The base is main, so GitHub also shows the catalog changes. Review only the live-volume changes.
Why
Controllers need to attach and detach writable disks on a running sandbox. Per-volume
attach_onlylets them mix mounted disks with devices whose mounts they manage themselves.What changed
attach_onlyin the API and Go and Python SDKs.Failed detach-result writes can leave an old attachment in the claims journal. Restart recovers its conservative hold; a successful retry clears the reference.
convergingmeans a volume request is active.Scope
Disk lifecycle and the combined controller sleep/wake example remain separate. Attach-only writers have no automatic dirty-marker protection. Changing a held volume's mode or mount requires removal first.
Upgrade the daemon and SDKs together. Older daemons can ignore the per-entry flag, and older Python clients reject it when callers reuse response entries in requests. The old claim-wide flag and saved empty-mount records remain supported.
Verification
The composed controller head
636c8d7contains this live daemon implementation and passes sandboxd and e2e race tests. The two-restart regression passes with the live detach interface. A failed result write recovers a conservative reader. An empty-target retry permits a writer, and the next restart recovers one writer without another attach.Go SDK race tests and 266 Python tests passed on
f7e5d12; the SDK and example trees are unchanged at636c8d7.The prior composed-stack run at
b3a5e4bpassed all four modes on Linux KVM with Cocoon v0.7.3 and Cloud Hypervisor v54. The SDK example completed detach, hibernate, daemon restart, wake, attach, and mount with disk identity and data preserved and no writer errors. Busy unmount and a simulated lost detach response kept workload access closed. That single-node run predates this rebase. The final controller head still needs a new VM run. Distributed reservations and access gating across nodes remain unverified.Performance
These historical measurements remain from
dc7a4e3; they have not been rerun for this head.Compared main
cf9280e, catalog09bb47b, and livedc7a4e3on Linux amd64, Go 1.27.1,GOMAXPROCS=1, pinned to CPU 48. Five alternating two-second samples used 5,000 claims and 5,000 checkpoint references. Values are microseconds, median [min, max].cf9280e09bb47bdc7a4e3Each scan checks all 5,000 states and uses 459,176 bytes and 20 allocations on every version. Commit uses about 43 KB and 19 allocations. Admission uses 584 bytes and six allocations on both measured versions. The overlapping scan ranges do not establish a stable difference. These runs do not measure fsync latency or end-to-end live attachment.