crash consistency
Power can fail, the kernel can panic, or the machine can be yanked off at any instant - including in the middle of writing to disk. Crash consistency is the question of what state your data and your filesystem are in when you boot back up after such an interruption. The unsettling truth is that the storage stack does NOT promise your last writes survived; it makes far narrower guarantees, and an application that wants its own data to be recoverable must build on exactly those narrow guarantees and no more.
Two hard realities frame this. First, writes are not instantaneous or all-or-nothing at the application's level: a single large write() may be split into several block writes, and a crash can land some and not others - and even a single block can be torn (half old, half new) if the device's atomic write unit is smaller than your block, or if a write was in flight when power died. Second, writes can be reordered: the page cache, the block layer, and the drive's own cache may commit your writes to the platter in a different order than you issued them, so you cannot assume that because write B finished after write A, B reached the disk after A. The only ordering you can truly rely on is the one you force with a durability barrier - fsync() - or that a journaling or copy-on-write filesystem provides for its own metadata. Everything else is a hope, not a guarantee.
Why it matters: real crash-safe formats (databases, message logs, careful config writers) are built from exactly these primitives - write data, fsync it, then write a small commit marker, fsync again, so a crash either leaves the marker (data is complete) or not (ignore the partial data). The honest, often-surprising point: 'the filesystem journaled, so I'm safe' protects the filesystem's own consistency, not your application's invariants across multiple files or records. If your program needs A and B to change together atomically, you must enforce that yourself with ordering and fsync; the storage stack will not do it for you, and assuming it does is a leading cause of corrupted data after a crash.
crash-safe commit pattern: write(data); fsync(fd); // step 1: data on stable storage write(commit_marker); fsync(fd); // step 2: marker AFTER data // crash before step 2 -> no marker -> ignore the partial data // crash after step 2 -> marker present -> data is known complete
Ordering by fsync turns 'maybe written' into a clean all-or-nothing: marker present iff data is complete.
A journaling filesystem keeps ITS OWN metadata consistent across a crash; it does not keep your application's cross-file or cross-record invariants. Writes can also be reordered and individual blocks torn, so the only inter-write ordering you can rely on is the one you force with fsync. Assuming the storage stack atomically commits your multi-step update is a leading cause of post-crash corruption.