Skip to content

Commit 092898b

Browse files
bvanasschegregkh
authored andcommitted
scsi: block: Fix a race in the runtime power management code
commit fa4d0f1 upstream. With the current implementation the following race can happen: * blk_pre_runtime_suspend() calls blk_freeze_queue_start() and blk_mq_unfreeze_queue(). * blk_queue_enter() calls blk_queue_pm_only() and that function returns true. * blk_queue_enter() calls blk_pm_request_resume() and that function does not call pm_request_resume() because the queue runtime status is RPM_ACTIVE. * blk_pre_runtime_suspend() changes the queue status into RPM_SUSPENDING. Fix this race by changing the queue runtime status into RPM_SUSPENDING before switching q_usage_counter to atomic mode. Link: https://lore.kernel.org/r/[email protected] Fixes: 986d413 ("blk-mq: Enable support for runtime power management") Cc: Ming Lei <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Cc: stable <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Jens Axboe <[email protected]> Acked-by: Alan Stern <[email protected]> Acked-by: Stanley Chu <[email protected]> Co-developed-by: Can Guo <[email protected]> Signed-off-by: Can Guo <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1a58c17 commit 092898b

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

block/blk-pm.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ int blk_pre_runtime_suspend(struct request_queue *q)
6767

6868
WARN_ON_ONCE(q->rpm_status != RPM_ACTIVE);
6969

70+
spin_lock_irq(&q->queue_lock);
71+
q->rpm_status = RPM_SUSPENDING;
72+
spin_unlock_irq(&q->queue_lock);
73+
7074
/*
7175
* Increase the pm_only counter before checking whether any
7276
* non-PM blk_queue_enter() calls are in progress to avoid that any
@@ -89,15 +93,14 @@ int blk_pre_runtime_suspend(struct request_queue *q)
8993
/* Switch q_usage_counter back to per-cpu mode. */
9094
blk_mq_unfreeze_queue(q);
9195

92-
spin_lock_irq(&q->queue_lock);
93-
if (ret < 0)
96+
if (ret < 0) {
97+
spin_lock_irq(&q->queue_lock);
98+
q->rpm_status = RPM_ACTIVE;
9499
pm_runtime_mark_last_busy(q->dev);
95-
else
96-
q->rpm_status = RPM_SUSPENDING;
97-
spin_unlock_irq(&q->queue_lock);
100+
spin_unlock_irq(&q->queue_lock);
98101

99-
if (ret)
100102
blk_clear_pm_only(q);
103+
}
101104

102105
return ret;
103106
}

0 commit comments

Comments
 (0)