ext4l: Add bh_cache_release_jbd() to clean up journal references

Add bh_cache_release_jbd() to forcibly release any journal_heads still
attached to buffer_heads after journal destroy. This must be called
after journal destroy but before bh_cache_clear() to ensure all
journal_heads are properly released, even if journal destroy did not
fully clean up (e.g., on abort).

The function clears b_bh in each journal_head to prevent use-after-free
when the buffer_head is later freed, and resets transaction pointers.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
Simon Glass
2025-12-29 14:29:32 -07:00
parent ab9cd9a045
commit b6980e8fca
2 changed files with 37 additions and 0 deletions

View File

@@ -2901,6 +2901,7 @@ void free_buffer_head(struct buffer_head *bh);
/* ext4l support functions (support.c) */
void ext4l_crc32c_init(void);
void bh_cache_release_jbd(void);
void bh_cache_clear(void);
int bh_cache_sync(void);
int ext4l_read_block(sector_t block, size_t size, void *buffer);

View File

@@ -335,6 +335,42 @@ void bh_cache_clear(void)
}
}
/**
* bh_cache_release_jbd() - Release all JBD references from buffer cache
*
* This must be called after journal destroy but before bh_cache_clear().
* It ensures all journal_heads are properly released from buffer_heads
* even if the journal destroy didn't fully clean up (e.g., on abort).
*/
void bh_cache_release_jbd(void)
{
int i;
struct bh_cache_entry *entry;
for (i = 0; i < BH_CACHE_SIZE; i++) {
for (entry = bh_cache[i]; entry; entry = entry->next) {
if (entry->bh && buffer_jbd(entry->bh)) {
struct buffer_head *bh = entry->bh;
struct journal_head *jh = bh2jh(bh);
/*
* Forcibly release the journal_head.
* Clear b_bh to prevent use-after-free when
* the buffer_head is later freed.
*/
if (jh) {
jh->b_bh = NULL;
jh->b_transaction = NULL;
jh->b_next_transaction = NULL;
jh->b_cp_transaction = NULL;
}
clear_buffer_jbd(bh);
bh->b_private = NULL;
}
}
}
}
/**
* bh_cache_sync() - Sync all dirty buffers to disk
*