diff options
author | Mike Snitzer <snitzer@redhat.com> | 2018-01-11 22:11:01 +0300 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-01-15 18:41:38 +0300 |
commit | 667257e8b2988c0183ba23e2bcd6900e87961606 (patch) | |
tree | ae0ec92e1fe69f71788169e07789096357f0c4ba /include/linux/genhd.h | |
parent | bc8d062c36e3525e81ea8237ff0ab3264c2317b6 (diff) | |
download | linux-667257e8b2988c0183ba23e2bcd6900e87961606.tar.xz |
block: properly protect the 'queue' kobj in blk_unregister_queue
The original commit e9a823fb34a8b (block: fix warning when I/O elevator
is changed as request_queue is being removed) is pretty conflated.
"conflated" because the resource being protected by q->sysfs_lock isn't
the queue_flags (it is the 'queue' kobj).
q->sysfs_lock serializes __elevator_change() (via elv_iosched_store)
from racing with blk_unregister_queue():
1) By holding q->sysfs_lock first, __elevator_change() can complete
before a racing blk_unregister_queue().
2) Conversely, __elevator_change() is testing for QUEUE_FLAG_REGISTERED
in case elv_iosched_store() loses the race with blk_unregister_queue(),
it needs a way to know the 'queue' kobj isn't there.
Expand the scope of blk_unregister_queue()'s q->sysfs_lock use so it is
held until after the 'queue' kobj is removed.
To do so blk_mq_unregister_dev() must not also take q->sysfs_lock. So
rename __blk_mq_unregister_dev() to blk_mq_unregister_dev().
Also, blk_unregister_queue() should use q->queue_lock to protect against
any concurrent writes to q->queue_flags -- even though chances are the
queue is being cleaned up so no concurrent writes are likely.
Fixes: e9a823fb34a8b ("block: fix warning when I/O elevator is changed as request_queue is being removed")
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'include/linux/genhd.h')
0 files changed, 0 insertions, 0 deletions