Skip to content

Commit

Permalink
blk-mq: blk_mq_freeze_queue() should allow nesting
Browse files Browse the repository at this point in the history
While converting to percpu_ref for freezing, add703f ("blk-mq:
use percpu_ref for mq usage count") incorrectly made
blk_mq_freeze_queue() misbehave when freezing is nested due to
percpu_ref_kill() being invoked on an already killed ref.

Fix it by making blk_mq_freeze_queue() kill and kick the queue only
for the outermost freeze attempt.  All the nested ones can simply wait
for the ref to reach zero.

While at it, remove unnecessary @wake initialization from
blk_mq_unfreeze_queue().

Signed-off-by: Tejun Heo <[email protected]>
Reported-by: Ming Lei <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
htejun authored and axboe committed Aug 22, 2014
1 parent a68aafa commit cddd5d1
Showing 1 changed file with 8 additions and 4 deletions.
12 changes: 8 additions & 4 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,22 @@ static void blk_mq_usage_counter_release(struct percpu_ref *ref)
*/
void blk_mq_freeze_queue(struct request_queue *q)
{
bool freeze;

spin_lock_irq(q->queue_lock);
q->mq_freeze_depth++;
freeze = !q->mq_freeze_depth++;
spin_unlock_irq(q->queue_lock);

percpu_ref_kill(&q->mq_usage_counter);
blk_mq_run_queues(q, false);
if (freeze) {
percpu_ref_kill(&q->mq_usage_counter);
blk_mq_run_queues(q, false);
}
wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
}

static void blk_mq_unfreeze_queue(struct request_queue *q)
{
bool wake = false;
bool wake;

spin_lock_irq(q->queue_lock);
wake = !--q->mq_freeze_depth;
Expand Down

0 comments on commit cddd5d1

Please sign in to comment.