volume-manager: consume medium_changed — the second removal trigger (S5)
The block client gains subscribeMedium / unsubscribeMedium / decodeMediumChanged (the reserved subscribe/unsubscribe verbs plus the MediumChanged decode), so a consumer never hand-rolls the wire format. The volume manager subscribes to each device it adopts and consumes the event through the new on_buffered_message seam — never the protocol dispatch, whose op numbers collide with the manager's own hello. A medium leaving while its device stays in the tree (a card reader, an eject) now runs the SAME kill-retire-remount path as a pulled stick: absent retires the volume, present re-probes it. That closes the "two triggers, one lifecycle" the architecture specifies — device-presence polling alone could never see a medium leave under a present device. dropDevice unsubscribes before closing so the driver's bounded subscriber table frees the slot; on a dead channel (a real pull) the call fails fast, proven by volume-removal still passing. New volume-medium-change case: eject the medium (not the device) -> "medium absent" -> the manager unmounts. Fails against a pre-S5 manager that never subscribed. Suite 132/132 (device-authority is the known child-cleanup flake, green on rerun).
This commit is contained in:
@@ -796,6 +796,25 @@ CASES = [
|
||||
"expect": r"(?s)fat: mounted /volumes/fat-12345678"
|
||||
r"[\s\S]*volume-manager: storage for volume \d+ removed; unmounting",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
# S5 medium_changed: the SECOND removal trigger. QMP-eject the MEDIUM (the
|
||||
# block backend, not the device) — the usb-storage device stays in the tree,
|
||||
# but its TEST UNIT READY poll reports not-ready and publishes medium_changed
|
||||
# (absent). The volume manager, now a subscriber, runs the same unmount path as
|
||||
# a device pull. Discrimination: before S5 the manager never subscribed, so the
|
||||
# event reached no one and the mount persisted (device-presence polling cannot
|
||||
# see a medium leave while the device stays). One lifecycle, two triggers.
|
||||
{"name": "volume-medium-change",
|
||||
"build_case": "fat-mount",
|
||||
"smp": 4,
|
||||
"timeout": 150,
|
||||
"qmp_sequence": [
|
||||
{"delay": 8, "command": "eject", "arguments": {"device": "bootusb", "force": True}},
|
||||
],
|
||||
"expect": r"(?s)fat: mounted /volumes/fat-12345678"
|
||||
r"[\s\S]*usb-storage: medium absent"
|
||||
r"[\s\S]*volume-manager: medium left a storage device; unmounting"
|
||||
r"[\s\S]*volume-manager: storage for volume \d+ removed; unmounting",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
# Volume-manager discovery + probe (V3a, docs/volume-manager-plan.md). Reuses
|
||||
# the fat-mount kernel build (the default boot now spawns the volume manager
|
||||
# from init.csv). It acquires the mass-storage block channel through the
|
||||
|
||||
Reference in New Issue
Block a user