diff options
author | Keith Busch <kbusch@kernel.org> | 2022-09-27 08:56:52 -0700 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2022-09-27 09:58:56 -0600 |
commit | 8237c01f1696bc53c470493bf1fe092a107648a6 (patch) | |
tree | b2e9718ee41d67d9a4bd3cfd57d241c5b648c744 /block/blk.h | |
parent | 568ec936bf1384fc15873908c96a9aeb62536edb (diff) | |
download | linux-rpi-8237c01f1696bc53c470493bf1fe092a107648a6.tar.gz linux-rpi-8237c01f1696bc53c470493bf1fe092a107648a6.tar.bz2 linux-rpi-8237c01f1696bc53c470493bf1fe092a107648a6.zip |
blk-mq: use quiesced elevator switch when reinitializing queues
The hctx's run_work may be racing with the elevator switch when
reinitializing hardware queues. The queue is merely frozen in this
context, but that only prevents requests from allocating and doesn't
stop the hctx work from running. The work may get an elevator pointer
that's being torn down, and can result in use-after-free errors and
kernel panics (example below). Use the quiesced elevator switch instead,
and make the previous one static since it is now only used locally.
nvme nvme0: resetting controller
nvme nvme0: 32/0/0 default/read/poll queues
BUG: kernel NULL pointer dereference, address: 0000000000000008
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 80000020c8861067 P4D 80000020c8861067 PUD 250f8c8067 PMD 0
Oops: 0000 [#1] SMP PTI
Workqueue: kblockd blk_mq_run_work_fn
RIP: 0010:kyber_has_work+0x29/0x70
...
Call Trace:
__blk_mq_do_dispatch_sched+0x83/0x2b0
__blk_mq_sched_dispatch_requests+0x12e/0x170
blk_mq_sched_dispatch_requests+0x30/0x60
__blk_mq_run_hw_queue+0x2b/0x50
process_one_work+0x1ef/0x380
worker_thread+0x2d/0x3e0
Signed-off-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20220927155652.3260724-1-kbusch@fb.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk.h')
-rw-r--r-- | block/blk.h | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/block/blk.h b/block/blk.h index 9f714c942d32..5350bf363035 100644 --- a/block/blk.h +++ b/block/blk.h @@ -270,8 +270,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, void blk_insert_flush(struct request *rq); -int elevator_switch_mq(struct request_queue *q, - struct elevator_type *new_e); +int elevator_switch(struct request_queue *q, struct elevator_type *new_e); void elevator_exit(struct request_queue *q); int elv_register_queue(struct request_queue *q, bool uevent); void elv_unregister_queue(struct request_queue *q); |