• M
    block: properly protect the 'queue' kobj in blk_unregister_queue · 667257e8
    Mike Snitzer 提交于
    The original commit e9a823fb (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: e9a823fb ("block: fix warning when I/O elevator is changed as request_queue is being removed")
    Signed-off-by: NMike Snitzer <snitzer@redhat.com>
    Reviewed-by: NMing Lei <ming.lei@redhat.com>
    Signed-off-by: NJens Axboe <axboe@kernel.dk>
    667257e8
blk-mq-sysfs.c 8.1 KB