fix(session): delete two dead accessors, make into_drive fallible

drive() and drive_mut() had ZERO callers — not in libfreemkv, freemkv,
autorip, bdemu, keysources or kdb. Deleted rather than converted: dead
public API that panics is not an API worth preserving the shape of.

into_drive() had two callers and now returns Result. The empty-slot
state is reachable through ordinary public use — stage_drive_as_reader
moves the drive into the reader slot, and calling into_drive twice moves
it out — so the panic was not guarding a caller error. identify() was
converted for exactly this reason in this same release; the fix went to
one of four public sinks and the other three were left.

I deferred this on the assumption the blast radius was large. It was
three call sites. Checking beats assuming.

Also fixes a REAL FLAKE in the gate, which is worth more than the above.
resolve_vid_only_bus_key_gate_reports_true_has_volume_id... failed about
one full-suite run in ten while passing every time in isolation. It
installed a capturing tracing subscriber to read back the has_volume_id
field of a warn.

That cannot be made reliable: dispatcher::set_default is THREAD-LOCAL
while tracing's callsite-interest cache is GLOBAL. The original author
knew, and called rebuild_interest_cache() — necessary but not
sufficient. I first serialised every capture in the crate behind one
lock (harness::with_captured_tracing, which also removed the same
hand-rolled dance from three other sites). Still 1-in-10, because the
cache can be re-evaluated against the process-default dispatch rather
than the thread-local one.

So the predicate is now a named function, handshake_has_volume_id, and
the test asserts the VALUE. A boolean does not need a subscriber to
check. The gate's hard-error behaviour keeps its own test.

Measured: 14 consecutive full-suite runs, 2994 passed, 0 failed.

A flaky gate is worse than a missing one — every green after it means
less, and this one had been eroding trust in the whole suite.
This commit is contained in:
Matthew Jackson
2026-07-30 21:18:13 -07:00
parent 5559987325
commit b86f7aef17
4 changed files with 146 additions and 47 deletions
+13 -16
View File
@@ -325,14 +325,6 @@ impl DiscSession {
self.disc.take()
}
/// Shared access to the opened drive (identity, profile, path). Panics if the
/// drive has already been staged into the reader slot
/// ([`Self::stage_drive_as_reader`]) or moved out via [`Self::into_drive`] —
/// use [`Self::device_path`] for a name that survives those moves.
pub fn drive(&self) -> &Drive {
self.drive.as_ref().expect("drive present")
}
/// The opened drive's device path. Cached at [`Self::open`], so it remains
/// available after [`Self::stage_drive_as_reader`] moves the drive into the
/// reader slot (the mux driver names the device here without the drive).
@@ -340,12 +332,6 @@ impl DiscSession {
&self.device
}
/// Mutable access to the opened drive — for ciphertext sampling and other
/// direct reads consumers still perform.
pub fn drive_mut(&mut self) -> &mut Drive {
self.drive.as_mut().expect("drive present")
}
/// Lock the tray so the disc cannot eject mid-rip. Unlock is guaranteed by
/// `Drive::drop`. A no-op if the drive is no longer held by the session.
pub fn lock_tray(&mut self) {
@@ -356,8 +342,19 @@ impl DiscSession {
/// Consume the session, returning the owned drive (e.g. to move into a
/// `DiscStream` for a live-drive mux).
pub fn into_drive(self) -> Drive {
self.drive.expect("drive present")
///
/// # Errors
///
/// [`Error::DeviceNotReady`] when the drive is no longer held — the PUBLIC
/// [`Self::stage_drive_as_reader`] moves it into the reader slot, and
/// calling this twice moves it out, so an empty slot is reachable through
/// ordinary use rather than being a caller error. A library must not panic
/// from public API, and a precondition that normal flow violates is a trap
/// rather than a contract.
pub fn into_drive(self) -> Result<Drive> {
self.drive.ok_or_else(|| Error::DeviceNotReady {
path: self.device.clone(),
})
}
/// Stage the owned drive as the session's boxed sector source so a live