RECOVERY JOURNAL.(9)
π recovery journal.(9) β Kernel API Manual π
okay so bestie, welcome to the Kernel API Manual page for recovery journal.(9) β the recovery journal, section 9, and it's giving "tiny log with main character energy" β¨. Here's the whole vibe, no details skipped, fr fr.
The recovery_journal provides a log of all block mapping and reference count changes which have not yet been stably written to the block map or slab journals. This log helps to reduce the write amplification of writes by providing amortization of slab journal and block map page updates. π«Ά
The recovery journal has a single dedicated queue and thread for performing all journal updates. The concurrency guarantees of this single-threaded model allow the code to omit more fine-grained locking for recovery journal structures. slay, honestly π
The journal consists of a set of on-disk blocks arranged as a circular log with monotonically increasing sequence numbers. Three sequence numbers serve to define the active extent of the journal:
headβ the oldest active block in the journal.tailβ the end of the half-open interval containing the active blocks.activeβ the number of the block actively receiving entries.
In an empty journal, head == active == tail. Once any entries are added, tail = active + 1, and head may be any value in the interval [tail - size, active]. π«
The journal also contains a set of in-memory blocks which are used to buffer up entries until they can be committed. In general the number of in-memory blocks (tail_buffer_count) will be less than the on-disk size. Each in-memory block is also a vdo_completion. Each in-memory block has a vio which is used to commit that block to disk. The vio's data is the on-disk representation of the journal block. In addition each in-memory block has a buffer which is used to accumulate entries while a partial commit of the block is in progress. In-memory blocks are kept on two lists. Free blocks live on the free_tail_blocks list. When a block becomes active (see below) it is moved to the active_tail_blocks list. When a block is fully committed, it is moved back to the free_tail_blocks list. π
When entries are added to the journal, they are added to the active in-memory block, as indicated by the active_block field. If the caller wishes to wait for the entry to be committed, the requesting VIO will be attached to the in-memory block to which the caller's entry was added. If the caller does wish to wait, or if the entry filled the active block, an attempt will be made to commit that block to disk. If there is already another commit in progress, the attempt will be ignored and then automatically retried when the in-progress commit completes. If there is no commit in progress, any data_vios waiting on the block are transferred to the block's vio which is then written, automatically waking all of the waiters when it completes. When the write completes, any entries which accumulated in the block are copied to the vio's data buffer. π¦
Finally, the journal maintains a set of counters, one for each on disk journal block. These counters are used as locks to prevent premature reaping of journal blocks. Each time a new sequence number is used, the counter for the corresponding block is incremented. The counter is subsequently decremented when that block is filled and then committed for the last time. This prevents blocks from being reaped while they are still being updated. The counter is also incremented once for each entry added to a block, and decremented once each time the block map is updated in memory for that request. This prevents blocks from being reaped while their VIOs are still active. Finally, each in-memory block map page tracks the oldest journal block that contains entries corresponding to uncommitted updates to that block map page. Each time an in-memory block map page is updated, it checks if the journal block for the VIO is earlier than the one it references, in which case it increments the count on the earlier journal block and decrements the count on the later journal block, maintaining a lock on the oldest journal block containing entries for that page. When a block map page has been flushed from the cache, the counter for the journal block it references is decremented. Whenever the counter for the head block goes to 0, the head is advanced until it comes to a block whose counter is not 0 or until it reaches the active block. This is the mechanism for reclaiming journal space on disk. π₯
If there is no in-memory space when a VIO attempts to add an entry, the VIO will be attached to the commit_completion and will be woken the next time a full block has committed. If there is no on-disk space when a VIO attempts to add an entry, the VIO will be attached to the
(and that's literally where the page cuts off, bestie π β not me inventing the rest, no cap.)
β¨ SEE ALSO β¨
- Kernel file
./drivers/md/dm-vdo/recovery-journal.h vdo_get_recovery_journal_block_number(9)vdo_compute_recovery_journal_check_byte(9)
mwah π this page is from ./drivers/md/dm-vdo, dated October 2026, and it's recovery journal.(9) β periodt. π«Ά
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms