Block One Thousand Twice

Metadata journaling is in use, so directory contents are journaled (directories are metadata) but regular file data is not. This sequence happens:

  1. A file is created inside directory foo, whose data block lives at block 1000. Transaction 1 journals I[foo] and D[foo] with final address 1000.
  2. The user deletes everything in foo and then foo itself. Block 1000 is freed.
  3. The user creates a regular file bar. The allocator hands it block 1000. Transaction 2 journals only I[bar]; bar's bytes are written straight to block 1000.
  4. Power is cut before either transaction has been checkpointed out of the journal.

A naive recovery replays every committed transaction in order. What goes wrong, and what does ext3 do about it?

A

Nothing goes wrong. The data bitmap replayed from transaction 2 marks block 1000 as owned by bar, and recovery skips journal writes that target a block owned by a different inode.

B

Replaying transaction 1 writes the old directory contents over block 1000, destroying bar's data. ext3 writes a revoke record when the directory is deleted, and recovery scans for revoke records first so revoked blocks are never replayed.

C

Nothing goes wrong. Transaction 2 has the higher sequence number and replays second, so block 1000 ends up holding bar's data.

D

Replaying transaction 1 corrupts block 1000, and ext3 prevents it by refusing to reallocate a freed block until the transaction that freed it has been checkpointed out of the journal.