v0.13.43: Pass 1 transport-failure recovery loop
This commit is contained in:
@@ -1,5 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.13.43 (2026-04-29)
|
||||||
|
|
||||||
|
### Pass 1 transport-failure recovery loop
|
||||||
|
|
||||||
|
- Transport failure (USB bridge crash) no longer kills the entire rip.
|
||||||
|
- Autorip re-discovers the drive after USB re-enumeration and resumes
|
||||||
|
from the mapfile. Up to 10 attempts.
|
||||||
|
- `Error::is_scsi_transport_failure()` now matches DiscRead with
|
||||||
|
status 0xFF (bridge crash) in addition to ScsiError.
|
||||||
|
- DriveSession tracks device_path for re-discovery.
|
||||||
|
|
||||||
## 0.13.42 (2026-04-29)
|
## 0.13.42 (2026-04-29)
|
||||||
|
|
||||||
### Fix: transport failure skips instead of aborting
|
### Fix: transport failure skips instead of aborting
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfreemkv"
|
name = "libfreemkv"
|
||||||
version = "0.13.42"
|
version = "0.13.43"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.86"
|
rust-version = "1.86"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|||||||
+5
-21
@@ -1281,7 +1281,6 @@ impl Disc {
|
|||||||
let mut buf = vec![0u8; batch as usize * 2048];
|
let mut buf = vec![0u8; batch as usize * 2048];
|
||||||
let mut bytes_done = 0u64;
|
let mut bytes_done = 0u64;
|
||||||
let mut halt_requested = false;
|
let mut halt_requested = false;
|
||||||
let mut consecutive_transport_failures: u32 = 0;
|
|
||||||
let copy_t0 = std::time::Instant::now();
|
let copy_t0 = std::time::Instant::now();
|
||||||
let mut iter_count: u64 = 0;
|
let mut iter_count: u64 = 0;
|
||||||
let mut read_ok_count: u64 = 0;
|
let mut read_ok_count: u64 = 0;
|
||||||
@@ -1362,7 +1361,6 @@ impl Disc {
|
|||||||
|
|
||||||
if read_result.is_ok() {
|
if read_result.is_ok() {
|
||||||
read_ok_count += 1;
|
read_ok_count += 1;
|
||||||
consecutive_transport_failures = 0;
|
|
||||||
if opts.decrypt {
|
if opts.decrypt {
|
||||||
crate::decrypt::decrypt_sectors(
|
crate::decrypt::decrypt_sectors(
|
||||||
&mut buf[..block_bytes as usize],
|
&mut buf[..block_bytes as usize],
|
||||||
@@ -1392,32 +1390,18 @@ impl Disc {
|
|||||||
let err = read_result.err().unwrap();
|
let err = read_result.err().unwrap();
|
||||||
read_err_count += 1;
|
read_err_count += 1;
|
||||||
|
|
||||||
let is_transport = err.is_scsi_transport_failure();
|
if err.is_scsi_transport_failure() {
|
||||||
|
|
||||||
if is_transport {
|
|
||||||
consecutive_transport_failures += 1;
|
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
target: "freemkv::disc",
|
target: "freemkv::disc",
|
||||||
phase = "transport_failure",
|
phase = "transport_failure",
|
||||||
lba = block_lba,
|
lba = block_lba,
|
||||||
consecutive = consecutive_transport_failures,
|
error = %err,
|
||||||
"transport failure (bridge crash); skipping block"
|
"transport failure (bridge crash); aborting copy — caller should USB reset + resume"
|
||||||
);
|
);
|
||||||
if consecutive_transport_failures >= 3 {
|
return Err(err);
|
||||||
tracing::warn!(
|
|
||||||
target: "freemkv::disc",
|
|
||||||
phase = "transport_failure_abort",
|
|
||||||
consecutive = consecutive_transport_failures,
|
|
||||||
"3 consecutive transport failures; aborting copy"
|
|
||||||
);
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
consecutive_transport_failures = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_transport
|
if !err.is_marginal_read()
|
||||||
&& !err.is_marginal_read()
|
|
||||||
&& err.scsi_sense().is_none_or(|s| !s.is_medium_error())
|
&& err.scsi_sense().is_none_or(|s| !s.is_medium_error())
|
||||||
{
|
{
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
|||||||
@@ -507,6 +507,12 @@ impl Error {
|
|||||||
status: crate::scsi::SCSI_STATUS_TRANSPORT_FAILURE,
|
status: crate::scsi::SCSI_STATUS_TRANSPORT_FAILURE,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
) || matches!(
|
||||||
|
self,
|
||||||
|
Error::DiscRead {
|
||||||
|
status: Some(crate::scsi::SCSI_STATUS_TRANSPORT_FAILURE),
|
||||||
|
..
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user