Re: [PATCH] btrfs: wait for in-flight readahead BIOs on open_ctree() error

From: Teng Liu

Date: Sun Mar 29 2026 - 13:23:51 EST


Thanks for your review!
On 2026-03-29 17:33, Qu Wenruo wrote:
>
>
> This doesn't make any sense to me.
It confuses me as well when I try to reproduce the bug. The reported
claimed that btrfs_bio_counter_sub triggered a use-after-free but this
function lives under `dev-reaplce.c` which should have nothing to do
with the setting from the name.

However when I checked the function call chain:

open_ctree()
→ btrfs_read_sys_array() # OK — sys_chunk_array in superblock is intact
→ load_super_root(chunk_root) # OK — reads root node, passes validation
→ btrfs_read_chunk_tree()
→ btrfs_for_each_slot()
→ readahead_tree_node_children(node)
→ for each child pointer in the internal node:
btrfs_readahead_node_child()
→ btrfs_readahead_tree_block()
→ read_extent_buffer_pages_nowait()
→ btrfs_submit_bbio()
→ btrfs_submit_chunk()
→ btrfs_bio_counter_inc_blocked() ← bio_counter++
→ btrfs_map_block()
→ submit_bio() ← sent to USB drive

After submit_bio() sends BIO to USB drive, we continue on
read_one_dev():

open_ctree()
→ btrfs_read_sys_array() # OK — sys_chunk_array in superblock is intact
→ load_super_root(chunk_root) # OK — reads root node, passes validation
→ btrfs_read_chunk_tree()
→ btrfs_for_each_slot()
→ readahead_tree_node_children(node)
→ bio_coutner++ and submit_bio() send BIO to USB drive
→ read_one_dev()

This read_one_dev will return an error since the leaf block is actually
corrupted. Then open_ctree will get into error path and try to free
fs_info.

After USB device finished BIO, it will try to decreament the counter but
the fs_info is already freed.

Any suggestions on this?


>
> The wait and counter are all for dev-reaplce, not matching your description
> of the generic metadata readahead.
>
> If you want to wait for all existing metadata reads, I didn't find a good
> helper, thus you will need to go through all extent buffers and wait for
> EXTENT_BUFFER_READING flags.
>
>