Β§42.3–42.5Solution #2: Journaling (Write-Ahead Logging)

Part III OSTEP pp. 531–542 Β· ~11 min read

  • journaling
  • transaction
  • checkpointing
  • write barrier
  • redo logging
  • circular log
  • data journaling
  • metadata journaling
  • revoke record
  • soft updates

Rather than repair inconsistencies after the fact, what if we prevented them? Journaling β€” write-ahead logging, borrowed from databases β€” does exactly that: before overwriting structures in place, first write a note describing the update to an on-disk log. If a crash strikes mid-update, recovery reads the note and finishes (or discards) the update β€” scanning only the log, not the whole disk.

42.3 Journaling: The Basic Idea

ext3 is just ext2 plus a journal β€” a reserved region (or separate device) that holds these notes:

ext2 (no journal)SuperGroup 0Group 1…Group Next3 (= ext2 + journal)SuperJournalGroup 0Group 1…Group N

Data journaling

Take our append (write I[v2], B[v2], Db). With data journaling , we first write the whole update to the log as a transaction : a transaction-begin block TxB (with the target addresses and a transaction id, TID), the blocks themselves, and a transaction-end block TxE. Once the transaction is safely logged, we checkpoint β€” checkpointing writes the blocks to their real homes, overwriting the old structures in place.

But how we write the transaction matters enormously:

Why you can't just write the whole transaction at once. The journal blocks are gold; a lost/garbage block is red.
JournalTxBid=1I[v2]B[v2]DbTxEid=1one big write β€” but the disk may reorder the pieces

1Tempting: issue all five blocks at once

Writing TxB, I[v2], B[v2], Db, and TxE as one big sequential write is fast. But the disk may schedule the pieces internally and complete them in ANY order.

step 1 / 5

The lesson: the disk can reorder an all-at-once write, so a valid-looking transaction could contain garbage. The fix is a two-step write β€” content first, then the atomic TxE. Getting the disk to honor this ordering needs a write barrier (some disks, alas, cheat and ignore barriers for speed). That gives the three-phase protocol: journal write β†’ journal commit (TxE) β†’ checkpoint.

Recovery

After a crash, recovery scans the log. A transaction that never committed (missing/mismatched TxE) is simply skipped. A committed transaction is replayed β€” its blocks re-written to their final locations. This is redo logging ; because a crash during checkpointing just re-does a few already-done writes, redundant redo is harmless. Recovery is now O(log size), not O(disk size).

Batching and the circular log

Committing every update separately would re-write the same blocks (e.g. an inode bitmap touched by two file creates) over and over. So file systems batch: buffer many updates into one global transaction, committed together after a few seconds. And since the log is finite, it’s a circular log β€” reused round and round. Once a transaction is checkpointed, its space is freed; a journal superblock records which transactions still need checkpointing:

Tx1Tx2Tx3Tx4freefreejournalsuperblockgreen = checkpointed β†’ space freedgold = committed, not yet checkpointedgray = free, ready to reusethe journal superblock tracks whichtransactions still need checkpointing

This adds a fourth phase: journal write β†’ commit β†’ checkpoint β†’ free.

42.3 (cont.) Metadata Journaling

Data journaling writes every data block twice (once to the log, once to its home) β€” roughly halving write bandwidth. Metadata journaling (ordered mode, the common choice) fixes this: it logs only metadata (inode, bitmaps, directories), never user data. The data block goes straight to its final location β€” but when? It must be written before the metadata is committed; otherwise the inode could be committed pointing at a block that never received its data (garbage). This is the core rule of crash consistency: write the pointed-to object before the object that points to it. So the protocols differ:

The two journaling protocols. Data journaling logs everything (safest, but writes data twice); metadata journaling logs only metadata and writes data to its final home first.
data journalingmetadata (ordered) journaling
1Journal write β€” TxB + metadata + DATA to the log; waitData write β€” write Db to its FINAL location; wait
2Journal commit β€” write TxE; wait β†’ committedJournal metadata write β€” TxB + metadata to the log; wait
3Checkpoint β€” write metadata + data to final locationsJournal commit β€” write TxE; wait β†’ committed
4Free β€” mark the transaction done in the journal superblockCheckpoint metadata β€” write metadata to final locations
5β€”Free β€” mark the transaction done in the journal superblock
Dotted-underlined cells have explanations β€” click one.

Tricky case: block reuse

Metadata journaling has a subtle hazard when a freed block is reused, which a revoke record solves:

The block-reuse hazard under metadata journaling β€” and how a revoke record fixes it.
JournalTxBid=1I[foo]D[foo]block 1000TxEid=1foo's directory data (block 1000) is in the log

1A directory block is logged

Directories are metadata, so when the user adds an entry to directory foo, foo's data block (say block 1000) is written to the journal.

step 1 / 4

42.4 Other Approaches

Journaling isn’t the only answer. Soft updates carefully orders writes so the disk is never inconsistent; copy-on-write ( COW , as in ZFS and the next chapter’s LFS) never overwrites in place, flipping a root pointer to swap in new structures atomically; and research approaches (backpointer-based, optimistic) push further still:

Four approaches to crash consistency.
core idearecovery costtrade-off
fscklet inconsistencies happen; scan & repair metadata at rebootO(disk size) β€” slowsimple idea, but prohibitively slow on large volumes
journalingwrite-ahead log; replay committed transactions after a crashO(log size) β€” fastthe popular choice (ext3/4, XFS, NTFS); ordered mode is the common sweet spot
soft updatescarefully order all writes so structures are never inconsistentfastno journal, but needs intricate FS-specific ordering rules β€” complex to build
copy-on-writenever overwrite in place; write new copies, then flip the root pointerfastconsistency is easy; used by ZFS and LFS (next chapter)
Dotted-underlined cells have explanations β€” click one.

42.5 Summary

The crash-consistency problem β€” updating persistent structures atomically despite crashes β€” has no free solution. fsck repairs after the fact but is O(disk size) and far too slow. Journaling writes a note ahead of time and replays it, cutting recovery to O(log size); its ordered metadata-journaling flavor is the popular sweet spot, keeping metadata consistent at modest cost. Next, LFS takes the log idea to its logical extreme β€” making the entire file system one big log.

Check yourself: journaling

1.What is the core idea of journaling (write-ahead logging)?

2.What does a transaction in the journal consist of?

3.Why can't the file system just issue all of a transaction's blocks (TxB, data, TxE) in one big write?

4.After a crash, how does recovery use the journal, and why is redundant replay harmless?

5.How does metadata (ordered) journaling differ from data journaling, and what ordering rule does it require?

6.What problem does a revoke record solve?

6 questions