Full crash durability: fsync the directory of every logged FS mutation - #2
Open
johanthoren wants to merge 4 commits into
Open
Full crash durability: fsync the directory of every logged FS mutation#2johanthoren wants to merge 4 commits into
johanthoren wants to merge 4 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1.
What
Makes every filesystem mutation
logmvrecords crash-durable by fsync'ing thedirectory whose entry each mutation changed: log creation, the move/trash
rename,
--mkdircreations, and--rmdirremovals. Before this, a log linecould outlive the directory entry it recorded across a crash (or the reverse),
because only the log file's contents were synced, never the containing
directories.
How
Pure standard library. No new dependency, no
unsafe, no platformcfgfor thesync:
sync_dir(dir)helper:File::open(dir)?.sync_all(). On a directory fdthat is
F_FULLFSYNCon macOS andfsyncon Linux, via the same std path thelog content already uses.
committed mutation and the log line that records it, so a crash can never
leave the log claiming an event whose filesystem effect was lost.
File::sync_data()is alreadyfcntl(F_FULLFSYNC)on macOS in std (library/std/src/sys/fs/unix.rs), so theoriginal idea that a hand-rolled
F_FULLFSYNCvialibc/rustixwas neededdoes not hold; no FFI is added.
append_lognow opens withcreate_new(true).append(true)and falls back toappend(true)onAlreadyExists, so it can fsync the log's parent directoryon first creation only. A side effect is that it refuses to follow a symlink
at the log path on creation (
O_EXCL).Sync failures after a committed mutation surface loudly through the existing
DriftAfter*errors. No new public error variant, no CLI flag, public APIunchanged.
Known follow-up
The
create_newchange makes a dangling-symlink log path fail loudly withENOENTinstead of creating through the link the waycreate(true)did. Thatis a degenerate configuration and arguably safer (it closes a symlink
append-redirect at the log path), but it is a behavior divergence worth
documenting or pinning with a test separately.
Tests
Existing suite green (40 tests). The durability effect is not observable without
power-loss injection, so this is a preserve-behavior change guarded by the
existing suite as non-regression, plus a security audit of the fsync placement
and the error mapping.