From 5fb771247f0b78fd9348beae455b8402f31645c3 Mon Sep 17 00:00:00 2001 From: Matthew Jackson Date: Fri, 24 Apr 2026 12:57:53 -0700 Subject: [PATCH] =?UTF-8?q?v0.12.1:=20cut=20non-recovery=20read=20timeout?= =?UTF-8?q?=205s=20=E2=86=92=201500ms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disc::copy fast pass (skip_on_error=true, recovery=false) was giving the drive 5 s per 64 KB block. On structure-protected / marginal UHD sectors the drive grinds L-EC for nearly the full budget per block, pinning throughput at ~13 KB/s even though skip_forward would happily skip past the region. 1500ms bounds the floor at ~43 KB/s/block. Recoverable sectors that would have succeeded at 3-5 s get picked up on Disc::patch (pass 2+) where recovery=true and the per-read budget is 30 s. --- Cargo.toml | 2 +- src/drive/mod.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e86f92f..5c91043 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfreemkv" -version = "0.12.0" +version = "0.12.1" edition = "2024" rust-version = "1.86" license = "AGPL-3.0-only" diff --git a/src/drive/mod.rs b/src/drive/mod.rs index 1bcd317..74b9c58 100644 --- a/src/drive/mod.rs +++ b/src/drive/mod.rs @@ -497,8 +497,15 @@ impl Drive { /// Returns Err only after all attempts exhausted — user should clean /// the disc and resume. pub fn read(&mut self, lba: u32, count: u16, buf: &mut [u8], recovery: bool) -> Result { + // Non-recovery mode is the Disc::copy fast pass — intent is "fail + // fast, let skip_forward advance past bad regions." A 5s budget let + // the drive grind L-EC on structure-protected / marginal sectors for + // nearly the full interval per 64 KB block, pinning throughput at + // ~13 KB/s on difficult discs. 1500ms kills slow reads early so + // skip_forward can double its stride; recoverable sectors are picked + // up on Disc::patch where recovery=true and the timeout is 30s. let timeout_ms = if !recovery { - 5_000 + 1_500 } else if self.recovery_bytes_remaining > 0 { 30_000 } else {