Artemis Milestone 2h: hot-detach -- 2h complete
blk_subsys_detach_device() (block_subsystem.c) walks the device chain, refuses removal of anything but the current tail (a mid-chain removal would corrupt every later slot's start_lbn -- this architecture's own doc already argues USB stays last specifically to avoid that), unlinks, shrinks total_user_lbn, closes and frees the slot. Discards rather than flushes dirty state -- the device is physically gone by the time this runs (PORTSC disconnect only). Trigger wiring mirrors the attach path: bot_msc_attached (set only once attach actually succeeds) gates a new bot_msc_detach_pending flag set at PORTSC disconnect (not Disable Slot completion, which is conditionally skipped and would miss concurrent connect/disconnect pairs), consumed in sk_repl_idle(). Advisor flagged the real hazard ahead of time: block_words.c's VM block window (blk_vm_lbn[]/blk_vm_cbuf[]) can go stale across a detach then a same-LBN re-attach, and suggested a pointer-identity re-check in blk_vm_load() as a minimal fix. That fix was implemented, then directly falsified by its own designed-for-this test: attach a blank device, read a block (populating the cache), detach, re-attach a device with distinct content at the identical LBN, read again -- served stale content from the first device. Root cause, confirmed live: glibc's allocator hands free(slot) straight back to the very next same-size calloc(), so the "fresh" and stale pointers were bitwise identical despite being two different devices. Fixed properly with a monotonic blk_subsys_epoch() counter (bumped on every attach/detach) checked by a new blk_vm_check_epoch() helper at the one choke point (blk_vm_find(), plus blk_vm_flush_all() which reads the same arrays directly) that covers every path touching the window cache -- unfooled by address reuse. Verified live with a new disk/usb-thumbdrive-test2.img fixture (distinct content from the existing blank test image): attach A, read (cache hit populated), detach, re-attach B at the same LBN, read again -- correctly ran a fresh device read and returned B's real content, not A's stale cached zeros. The failing pointer-comparison attempt's own capture log kept as evidence, not deleted. All three architectures re-verified clean. FABRIC-2.md Section X 2h marked complete -- enumeration through hot-detach all live and verified; only WRITE(10) (2g's own still-open item) remains unimplemented in the driver, not blocking anything here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3b085dd875
commit
af267a52a6
+17
-3
@@ -98,18 +98,32 @@ static void sk_repl_idle(void)
|
||||
* busy-wait -- which blkio_usb_open_msc() uses internally -- must
|
||||
* never run from inside xhci_poll_events()'s own call frame). */
|
||||
xhci_dev_t *xdev = xhci_get_dev();
|
||||
static blkio_dev_t usb_blk_dev; /* single-device scope, matching the xHCI
|
||||
* driver's own; referenced by both the
|
||||
* attach and detach handling below. */
|
||||
if (xdev && xdev->bot_msc_attach_pending) {
|
||||
xdev->bot_msc_attach_pending = 0;
|
||||
uint32_t slot_id = xdev->bot_msc_attach_slot_id;
|
||||
|
||||
static blkio_dev_t usb_blk_dev;
|
||||
int rc = blkio_usb_open_msc(&usb_blk_dev, xdev, slot_id);
|
||||
if (rc == 0) {
|
||||
blk_subsys_attach_device(&usb_blk_dev);
|
||||
if (rc == 0 && blk_subsys_attach_device(&usb_blk_dev) == BLK_OK) {
|
||||
xdev->bot_msc_attached = 1;
|
||||
} else {
|
||||
console_println("xhci: USB MSC block-subsystem attach failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* Milestone 2h hot-detach: the device disconnected (PORTSC, inside the
|
||||
* xhci_poll_events() call above) after having actually attached.
|
||||
* blk_subsys_detach_device() is local block_subsystem.c bookkeeping --
|
||||
* no device round-trip, so it wouldn't strictly need to run outside
|
||||
* xhci_poll_events()'s own call frame -- but handling it here anyway
|
||||
* matches the attach path's shape and keeps xhci.c decoupled from
|
||||
* block_subsystem.c (see bot_msc_detach_pending's own doc comment). */
|
||||
if (xdev && xdev->bot_msc_detach_pending) {
|
||||
xdev->bot_msc_detach_pending = 0;
|
||||
blk_subsys_detach_device(&usb_blk_dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user