section_recover: per-rip handler scorecard + Bisect-leads-scouts + proportional Jump

Scorecard: grade each handler by recovery rate (MB/s) per rip, order
best-first on later sections, log the ranking at pass end. Untried
handlers rank top so each is calibrated once before ranking narrows to
the winners. Ephemeral (reset per pass), no persistence.

Tier 0 scouts are now [Bisect, Jump, Linear-fast x2], scorecard-ordered.
Bisect leads: probing the MIDDLE of a range lands on a readable island in
one read where a linear scan grinds the dead front to reach it. Jump now
jumps to the middle of the REMAINING span (proportional) instead of a
fixed 8 MiB that leapt clean over small ranges and missed their readable
middles. Tier 1 is slow deep-recovery on the residue.
This commit is contained in:
Matthew Jackson
2026-06-30 21:26:35 -07:00
parent 840ba8390c
commit 29f76aad68
+3 -9
View File
@@ -42,16 +42,10 @@ const SECTOR: u64 = 2048;
/// spans against granularity on dead ones. /// spans against granularity on dead ones.
const BATCH_SECTORS: u64 = 32; const BATCH_SECTORS: u64 = 32;
/// `Jump` handler: after this many consecutive failed batches, skip ahead to /// `Jump` handler: after this many consecutive failed batches it jumps to the
/// find where readable data resumes rather than reading every dead sector. /// middle of the remaining span (see the handler) to find where readable data
/// resumes rather than reading every dead sector.
const JUMP_AFTER_FAILS: u32 = 2; const JUMP_AFTER_FAILS: u32 = 2;
/// `Jump` initial skip distance; doubles after each jump, capped at
/// [`JUMP_CAP_BYTES`]. Starts large so a big dead region is cleared in a handful
/// of ~10 s probe reads instead of a dozen (each dead read costs the drive's
/// full timeout). A skipped span is left bad for Bisect to reclaim any readable
/// islands, so an over-jump loses nothing — it just defers precision.
const JUMP_BASE_BYTES: u64 = 8 << 20; // 8 MiB
const JUMP_CAP_BYTES: u64 = 256 << 20; // 256 MiB
/// Where a handler left the section after its bounded attempt. /// Where a handler left the section after its bounded attempt.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]