Skip to main content

max / audiofiles

fsync store blobs before rename for crash durability (ultra-fuzz Core Integrity) The content-addressed import wrote a temp blob and rename-swapped it into place but never fsynced, so a power loss could leave the rename durable while the bytes were not — a garbage blob at the canonical path that the store would trust forever. sync_all the temp file before the rename, and best-effort fsync the parent directory after so the dirent is durable too. Both failures are ignored: they only weaken durability, never fail the import. Deferred (recorded, NOTE-level): the needs_write size-trust dedup repair (verify_sample is the intended backstop) and the same-process temp-name race (unreachable under the serial side-effect invariant). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-06-18 21:03 UTC
Commit: 670c669172270a825288ac07c3f9a6c09d36f615
Parent: 4eca951
1 file changed, +15 insertions, -0 deletions
@@ -179,10 +179,25 @@ impl SampleStore {
179 179 if needs_write {
180 180 let tmp = dest.with_file_name(format!("{hash}.{ext}.{}.tmp", std::process::id()));
181 181 fs::copy(path, &tmp).map_err(|e| io_err(&tmp, e))?;
182 + // fsync the blob bytes to disk before the rename. Without this the
183 + // rename can be durable while the file contents are not, leaving a
184 + // canonical-path blob with garbage after a power loss — which a
185 + // content-addressed store would then trust forever.
186 + if let Ok(f) = fs::File::open(&tmp) {
187 + let _ = f.sync_all();
188 + }
182 189 if let Err(e) = fs::rename(&tmp, &dest) {
183 190 let _ = fs::remove_file(&tmp);
184 191 return Err(io_err(&dest, e));
185 192 }
193 + // Best-effort fsync of the directory so the rename itself is durable
194 + // (the new dirent survives a crash). Not all filesystems support
195 + // directory fsync; failure here only weakens durability, never the
196 + // import.
197 + if let Some(parent) = dest.parent()
198 + && let Ok(d) = fs::File::open(parent) {
199 + let _ = d.sync_all();
200 + }
186 201 // Mark the canonical blob read-only. The VFS mirror exposes store
187 202 // blobs to DAWs/file managers via symlinks; a "save in place" would
188 203 // otherwise write through and corrupt the SHA-256-named blob,