mirror of
https://github.com/freemkv/libfreemkv.git
synced 2026-10-07 18:13:10 +00:00
Pass N now reads at 32 sectors per attempt and drops to 1 only on batch-read failure to probe each sector individually. After 16 consecutive clean single-sector reads it climbs back to 32. Net effect: NonTrimmed regions walk ~32x faster in clean stretches without sacrificing per-sector recovery quality — the drop-to-1 retry from the same cursor position guarantees every sector in a failed batch is individually attempted. Design contract: - A batch-read failure (count > 1) is NOT a recorded failure: no NonTrimmed mark, no consecutive_failures bump, no damage_window push, cursor stays put. We just drop current_batch to 1 and the loop re-attempts the same position at single-sector granularity. - A single-sector failure (count == 1) follows the existing path: NonTrimmed mark, consecutive_failures++, damage_window.push(false), post-failure pause, wedge probes. - Backtrack always at count=1: this path fills a gap that the main loop's damage-window skip jumped over. Using batched reads there would lump good sectors into NonTrimmed marks when the gap contains even one bad sector. State machine adds: - `initial_batch` (from opts.block_sectors, default 32 in patch_internal) - `current_batch` (mutable, starts at initial_batch, drops to 1 on batch failure) - `consecutive_singles_ok` (counter, resets on upscale + failure) - `ADAPTIVE_UPSCALE_THRESHOLD = 16` (matches sweep's pattern for "16 consecutive good = back to fast mode") Tests: - pass_n_size_aware_skip.rs PatternedSectorReader now fills each sector with its OWN LBA byte (not the starting LBA's byte). This matches real drive behavior — the pre-0.18.13 fixture's "fill whole batch with one byte" was a shortcut that only worked when patch read 1 sector at a time. Existing recovery-quality assertions all still pass under adaptive batching. User spec: "try 32, pass, great, fail -> do 1 sector"