v0.20.3: add halt check to Disc::patch backtrack inner loop

WO-5 (partial): the patch backtrack inner loop ('while bt_pos <
backtrack_end' in disc/patch.rs) issues per-sector reads to fill the
gap created by a damage-window skip. A long backtrack span can run
minutes; without an inline halt poll, the outer halt only takes
effect when control returns to the per-range loop. Adds a halt poll
at the top of each iteration so cancellation propagates inside the
backtrack span.

Per-sector read failures inside the backtrack already drop through
to the main fail path; this only changes the cancellation latency
between an /api/stop call and the producer actually unwinding. Drops
worst-case unwind from 'whole backtrack span × per-sector recovery
timeout' (minutes) to 'one in-flight SCSI command' (seconds).

The broader Arc<AtomicBool> → Halt migration on CopyOptions /
SweepOptions / PatchOptions / Drive::halt and Pipeline::send halt-
awareness is deferred — separate cycle, larger API impact.
This commit is contained in:
MattJackson
2026-05-13 11:55:52 -07:00
parent d7243a6044
commit 005f887bf9
2 changed files with 13 additions and 1 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "libfreemkv"
version = "0.20.2"
version = "0.20.3"
edition = "2024"
rust-version = "1.86"
license = "AGPL-3.0-only"
+12
View File
@@ -895,6 +895,18 @@ impl Disc {
);
let mut bt_pos = backtrack_start;
while bt_pos < backtrack_end {
// Honor cancellation inside the
// backtrack inner loop. A long
// backtrack span can run minutes
// of single-sector reads; without
// this check the outer halt only
// takes effect when control
// returns to the per-range loop.
if let Some(h) = &opts.halt {
if h.load(std::sync::atomic::Ordering::Relaxed) {
return Err(crate::error::Error::Halted);
}
}
let span =
// Backtrack always at count=1: this path
// fills a gap that the main loop's damage-