diff options
| author | Yu Kuai <[email protected]> | 2023-05-31 07:34:35 +0000 |
|---|---|---|
| committer | Jens Axboe <[email protected]> | 2023-06-01 15:13:31 +0000 |
| commit | 5a0ac57c48aa9380126bd9bf3ec82140aab84548 (patch) | |
| tree | 7d440f4a22f244eea9dfbcd27edc62457f923c9a /fs/btrfs/dev-replace.c | |
| parent | block: mark bio_add_folio as __must_check (diff) | |
| download | kernel-5a0ac57c48aa9380126bd9bf3ec82140aab84548.tar.gz kernel-5a0ac57c48aa9380126bd9bf3ec82140aab84548.zip | |
blk-ioc: protect ioc_destroy_icq() by 'queue_lock'
Currently, icq is tracked by both request_queue(icq->q_node) and
task(icq->ioc_node), and ioc_clear_queue() from elevator exit is not
safe because it can access the list without protection:
ioc_clear_queue ioc_release_fn
lock queue_lock
list_splice
/* move queue list to a local list */
unlock queue_lock
/*
* lock is released, the local list
* can be accessed through task exit.
*/
lock ioc->lock
while (!hlist_empty)
icq = hlist_entry
lock queue_lock
ioc_destroy_icq
delete icq->ioc_node
while (!list_empty)
icq = list_entry() list_del icq->q_node
/*
* This is not protected by any lock,
* list_entry concurrent with list_del
* is not safe.
*/
unlock queue_lock
unlock ioc->lock
Fix this problem by protecting list 'icq->q_node' by queue_lock from
ioc_clear_queue().
Reported-and-tested-by: Pradeep Pragallapati <[email protected]>
Link: https://lore.kernel.org/lkml/[email protected]/
Signed-off-by: Yu Kuai <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jens Axboe <[email protected]>
Diffstat (limited to 'fs/btrfs/dev-replace.c')
0 files changed, 0 insertions, 0 deletions
