Fix Windows multi-drive selection, disk:// alias, and READ chunking
Three fixes for a Windows ASUS Blu-ray drive that failed/spammed errors: - resolve.rs: accept disk:// as an alias for disc:// (identical behavior; empty = auto-detect, path = device). Windows users commonly type disk://i: after the drive-letter convention. - drive::find_drive: prefer a drive that reports media present. Enumerate all optical drives, query Drive::drive_status() (GET EVENT STATUS, works regardless of firmware), and return the first reporting DiscPresent; fall back to the first enumerated drive when none report a disc so single-drive / quirky setups don't regress. Selection policy split into select_drive_with_media() for unit testing. - READ chunking: add ScsiTransport::max_transfer_bytes() (default 1 MiB). Windows SPTI overrides it with the adapter MaximumTransferLength queried via IOCTL_STORAGE_QUERY_PROPERTY / StorageAdapterProperty, clamped to a 64 KiB floor (fallback on query failure). Drive::read now caps each READ(10) to that limit: small reads take the unchanged single-CDB path, larger reads loop over read_one() chunks, reporting the failing chunk's LBA on error. This stops the 16 MiB single read that exceeded the adapter limit, made DeviceIoControl fail, and spammed transport-failure warnings with slow tiny-read fallbacks. Tests added for the disk:// alias, media-preference selection, and READ chunk decomposition / per-chunk error LBA.
This commit is contained in:
@@ -319,6 +319,23 @@ pub trait ScsiTransport: Send {
|
||||
data: &mut [u8],
|
||||
timeout_ms: u32,
|
||||
) -> Result<ScsiResult>;
|
||||
|
||||
/// Maximum number of bytes the transport can carry in a single SCSI
|
||||
/// data-in transfer. A READ that requests more than this must be split
|
||||
/// into chunks by the caller ([`crate::Drive::read`]) — otherwise the
|
||||
/// transport fails the whole command.
|
||||
///
|
||||
/// The default is a conservative 1 MiB, safe on every platform. The
|
||||
/// Windows backend overrides this with the adapter's real
|
||||
/// `MaximumTransferLength` (queried via `IOCTL_STORAGE_QUERY_PROPERTY`):
|
||||
/// a 16 MiB READ that exceeds the adapter limit makes
|
||||
/// `DeviceIoControl` fail outright, which freemkv then mis-reads as a
|
||||
/// transport failure and falls back to slow, log-spamming tiny reads.
|
||||
/// Chunking to this limit fixes that. Linux/macOS keep the 1 MiB
|
||||
/// default (well within any real `max_sectors_kb`).
|
||||
fn max_transfer_bytes(&self) -> usize {
|
||||
1 << 20
|
||||
}
|
||||
}
|
||||
|
||||
// ── Platform-agnostic open / reset ──────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user