From af47d4198946e6b73314461f425608d2944bf044 Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Sun, 9 Aug 2026 20:27:58 +0100 Subject: [PATCH] volume-manager: removal supersedes a pending restart in the poll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inline V4 review (the boundary-review workflow stalled): the poll ran a due fat-restart before the presence check and returned, so a fat death followed by a device removal would respawn fat against the now-dead channel and churn until the crash cap before the removal was noticed. Reorder: check the specific device's presence first (unmount if gone), and only fire a due restart once the device is confirmed present. Neutral: fat-mount, volume-removal, amd-iommu-usb-storage green. Noted V4 limitations (not fixed here, edge cases outside the user unplug case): a usb-storage DRIVER crash (device stays, driver restarts with a new endpoint) leaves fat holding a dead channel — the device is still present so removal is not detected; fat would need to observe its channel death and exit. Deferred with the medium_changed subscription and multi-volume. --- .../volume-manager/volume-manager.zig | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/system/services/volume-manager/volume-manager.zig b/system/services/volume-manager/volume-manager.zig index 6d72f4e..c00dbe4 100644 --- a/system/services/volume-manager/volume-manager.zig +++ b/system/services/volume-manager/volume-manager.zig @@ -240,17 +240,21 @@ fn removeVolume() void { fs_failed = false; } -/// One poll tick: perform a due restart, else reconcile presence — mount a newly -/// present volume, unmount a departed one. +/// One poll tick. Removal is checked FIRST and supersedes a pending restart: if +/// the device is gone there is nothing to restart fat onto, and respawning it +/// against the dead channel would just churn until the crash cap. Only once the +/// device is confirmed present does a due restart fire. fn pollTick() void { - if (restart_pending and time.clock() >= restart_due_ns) { - restart_pending = false; - if (volume) |*v| spawnFilesystem(v); - return; - } if (volume) |v| { // Serving: watch for the specific device leaving (a pulled stick). - if (!isDevicePresent(v.storage_device_id)) removeVolume(); + if (!isDevicePresent(v.storage_device_id)) { + removeVolume(); + return; + } + if (restart_pending and time.clock() >= restart_due_ns) { + restart_pending = false; + spawnFilesystem(&volume.?); + } } else { // Idle: try to bring a present storage device up. bringUpVolume();