Operating Systems Reference/Persistence & I/O

Journaling & Crash Consistency

What happens when power fails mid-write — the crash-consistency problem, fsync/sync semantics, write-ahead logging in file systems, and the parallel to database transaction logs.

4/5Overview: 30m

The crash-consistency problem

Updating a file may touch inode, bitmap, and data block separately. Power loss mid-update leaves the file system inconsistent — free block referenced twice, or allocated block orphaned. FSCK repairs offline; journaling prevents the need.

Write ordering without journaling

A single append may require:

  1. Allocate data block (bitmap)
  2. Write data
  3. Update inode size/pointer

Crash after step 1 but before 3 → leaked block. Crash after 3 but before 2 → file points at garbage. Production systems need atomicity for metadata transitions.

Journaling protocol (simplified)

  1. Write intended changes to journal (log) on disk.
  2. Commit journal entry (single fsync of log).
  3. Apply changes to main file system structures (checkpoint).
  4. Mark journal entry complete.

Recovery after crash: replay committed journal entries. Same pattern as database WAL.

Data journaling vs metadata journaling

ModeJournalsTrade-off
Metadata only (ordered)Inode/bitmap changesFast; data may be stale on crash
Full data journalingData + metadataSafer; 2× write traffic

ext4 defaults to ordered mode — data flushed before metadata commit.

fsync and durability

write() returns when data hits the page cache — not necessarily disk. fsync(fd) forces dirty pages and metadata to stable storage. Databases call fsync on commit; that's the latency you pay for durability.

Senior-level signal

"Postgres is slow on ext4" often traces to barrier=0 history or cloud volumes lying about flush — not query plans. Benchmark with pg_test_fsync. For application logs, batch writes and accept loss on crash rather than fsync per line.

Where this goes next

Virtual Machines vs Containers shifts from persistence to isolation — how workloads share a kernel without sharing each other's view of processes, network, and filesystem.

Further Reading

Hands-On Tasks (Optional)

Low-setup exercises on your local machine. No autograding — the goal is to build intuition, not pass a test.

  • Measure buffered vs fsync'd writes

    Python: write 10MB to a file with `f.write(data)` and time it; then repeat with `f.write(data); os.fsync(f.fileno())`. fsync should be slower — that's the cost of durability.

    15m