diff options
author | Mike Snitzer <snitzer@redhat.com> | 2016-09-01 11:59:33 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-09-14 13:56:38 -0400 |
commit | 9dbeaeabacb26260d1621fe58f0f6fdedc8860d4 (patch) | |
tree | 4a2ead82f0a872b5046b44df407b37ca8a3065a9 | |
parent | 2397a15aff35b5b4eed732ce81fda5a9d15053f9 (diff) | |
download | linux-9dbeaeabacb26260d1621fe58f0f6fdedc8860d4.tar.gz linux-9dbeaeabacb26260d1621fe58f0f6fdedc8860d4.tar.bz2 linux-9dbeaeabacb26260d1621fe58f0f6fdedc8860d4.zip |
dm rq: take request_queue lock while clearing QUEUE_FLAG_STOPPED
Every call of queue_flag_clear_unlocked() after block device
initialization has finished is wrong if blk_cleanup_queue() can be
called concurrently. Convert queue_flag_clear_unlocked() into
queue_flag_clear() and protect it by the block layer queue lock.
Also, factor out dm_mq_start_queue().
Reported-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org
-rw-r--r-- | drivers/md/dm-rq.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 2f605f62e47d..bd3ba97d44a2 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -73,15 +73,24 @@ static void dm_old_start_queue(struct request_queue *q) spin_unlock_irqrestore(q->queue_lock, flags); } +static void dm_mq_start_queue(struct request_queue *q) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + queue_flag_clear(QUEUE_FLAG_STOPPED, q); + spin_unlock_irqrestore(q->queue_lock, flags); + + blk_mq_start_stopped_hw_queues(q, true); + blk_mq_kick_requeue_list(q); +} + void dm_start_queue(struct request_queue *q) { if (!q->mq_ops) dm_old_start_queue(q); - else { - queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, q); - blk_mq_start_stopped_hw_queues(q, true); - blk_mq_kick_requeue_list(q); - } + else + dm_mq_start_queue(q); } static void dm_old_stop_queue(struct request_queue *q) |