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
This commit is contained in:
@ -73,15 +73,24 @@ static void dm_old_start_queue(struct request_queue *q)
|
|||||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
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)
|
void dm_start_queue(struct request_queue *q)
|
||||||
{
|
{
|
||||||
if (!q->mq_ops)
|
if (!q->mq_ops)
|
||||||
dm_old_start_queue(q);
|
dm_old_start_queue(q);
|
||||||
else {
|
else
|
||||||
queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, q);
|
dm_mq_start_queue(q);
|
||||||
blk_mq_start_stopped_hw_queues(q, true);
|
|
||||||
blk_mq_kick_requeue_list(q);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dm_old_stop_queue(struct request_queue *q)
|
static void dm_old_stop_queue(struct request_queue *q)
|
||||||
|
Reference in New Issue
Block a user