v0.17.13: thread Writer through patch + mux for big-write consistency

The bounded-cache writeback wrapper (crate::io::Writer) was added in
0.17.10 and wired into Disc::sweep in 0.17.11, but the other two
paths in the crate that write large amounts of data sequentially —
Disc::patch and the MKV/M2TS mux — were still operating on raw
std::fs::File. That meant the dirty-page burst pathology the wrapper
exists to prevent could still bite on slow / network-attached staging
during recovery and mux phases.

This release plugs those gaps:

- Disc::patch (disc/mod.rs:1981) now wraps the reopened ISO in
  Writer before any seek / write. sync_all on Writer cleanly drains
  the in-flight chunk before the existing fsync.
- mux/resolve.rs MKV and M2TS branches wrap the output File in
  Writer underneath BufWriter. UHD MKV mux routinely produces 70+ GB
  of sequential output; the page cache no longer absorbs that as a
  single hot blast on slow targets.

Mapfile, log, settings, history, and stream-pipeline byte buffers
remain unchanged: those are either small one-shot writes (where
the wrapper has zero benefit and adds a stream_position syscall) or
already use bounded persistence (mapfile time-batched in 0.17.12).
The principle: any path that writes substantial sequential data to
a single file uses Writer; trivial writes don't.
This commit is contained in:
2026-05-09 06:32:08 -07:00
parent b79c973c1d
commit 40fd44e63a
4 changed files with 49 additions and 5 deletions
+5 -1
View File
@@ -1978,10 +1978,14 @@ impl Disc {
let is_regular = std::fs::metadata(path)
.map(|m| m.file_type().is_file())
.unwrap_or(false);
let mut file = std::fs::OpenOptions::new()
let file = std::fs::OpenOptions::new()
.write(true)
.open(path)
.map_err(|e| Error::IoError { source: e })?;
// Same bounded-cache writeback wrapper sweep uses, so patch's
// recovery writes (sparse but can be many across a damaged region)
// get the burst-flush protection on slow / NFS-backed staging.
let mut file = crate::io::Writer::new(file).map_err(|e| Error::IoError { source: e })?;
// Log ISO file size at patch start for write monitoring
if let Ok(metadata) = std::fs::metadata(path) {
+11 -3
View File
@@ -242,15 +242,23 @@ pub fn output(
match parsed {
StreamUrl::Mkv { ref path } => {
validate_file_path(path, "mkv")?;
// Wrap the raw `File` in `crate::io::Writer` (bounded-cache
// writeback) so a UHD-scale MKV mux to slow / network-attached
// staging doesn't hit the dirty-page burst pathology that
// sweep already side-steps. BufWriter sits on top to coalesce
// mux's many small EBML element writes.
let file = std::fs::File::create(path)?;
let writer: Box<dyn super::WriteSeek> =
Box::new(std::io::BufWriter::with_capacity(IO_BUF_SIZE, file));
let writer: Box<dyn super::WriteSeek> = Box::new(std::io::BufWriter::with_capacity(
IO_BUF_SIZE,
crate::io::Writer::new(file)?,
));
Ok(Box::new(MkvStream::create(writer, title)?))
}
StreamUrl::M2ts { ref path } => {
validate_file_path(path, "m2ts")?;
let file = std::fs::File::create(path)?;
let writer = std::io::BufWriter::with_capacity(IO_BUF_SIZE, file);
let writer =
std::io::BufWriter::with_capacity(IO_BUF_SIZE, crate::io::Writer::new(file)?);
Ok(Box::new(M2tsStream::create(writer, title)?))
}
StreamUrl::Network { ref addr } => {