blk-mq: free the bitmaps of tags in the SRCU callback

Commit ad0d05dbdd keeps struct blk_mq_tags and the requests until the
iterators under tags_srcu are gone, but the two bitmaps they walk are
still freed right away. When the number of hardware queues shrinks,
blk_mq_tagset_busy_iter() may be about to walk tags that
__blk_mq_update_nr_hw_queues() frees. sbitmap_free() clears the map
pointer, so that's a NULL dereference or a use-after-free, depending on
the timing.

Free the bitmaps with the rest in the callback.

Fixes: ad0d05dbdd ("blk-mq: Defer freeing of tags page_list to SRCU callback")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Link: https://patch.msgid.link/20261028164415.1262013-44-axboe@kernel.dk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Josef Bacik 2026-10-28 10:41:46 -06:00 committed by Jens Axboe
parent 6c55f94317
commit 10b249e9b0

View File

@ -611,17 +611,17 @@ static void blk_mq_free_tags_callback(struct rcu_head *head)
kmemleak_free(page_address(page));
__free_pages(page, page->private);
}
/* An iterator may walk the bitmaps for as long as it may see the tags */
sbitmap_queue_free(&tags->bitmap_tags);
sbitmap_queue_free(&tags->breserved_tags);
kfree(tags);
}
void blk_mq_free_tags(struct blk_mq_tags *tags)
{
sbitmap_queue_free(&tags->bitmap_tags);
sbitmap_queue_free(&tags->breserved_tags);
/* if tags pages is not allocated yet, free tags directly */
if (list_empty(&tags->page_list)) {
kfree(tags);
blk_mq_free_tags_callback(&tags->rcu_head);
return;
}