Skip to content

Commit 52abca6

Browse files
AlanSternmartinkpetersen
authored andcommitted
scsi: block: Do not accept any requests while suspended
blk_queue_enter() accepts BLK_MQ_REQ_PM requests independent of the runtime power management state. Now that SCSI domain validation no longer depends on this behavior, modify the behavior of blk_queue_enter() as follows: - Do not accept any requests while suspended. - Only process power management requests while suspending or resuming. Submitting BLK_MQ_REQ_PM requests to a device that is runtime suspended causes runtime-suspended devices not to resume as they should. The request which should cause a runtime resume instead gets issued directly, without resuming the device first. Of course the device can't handle it properly, the I/O fails, and the device remains suspended. The problem is fixed by checking that the queue's runtime-PM status isn't RPM_SUSPENDED before allowing a request to be issued, and queuing a runtime-resume request if it is. In particular, the inline blk_pm_request_resume() routine is renamed blk_pm_resume_queue() and the code is unified by merging the surrounding checks into the routine. If the queue isn't set up for runtime PM, or there currently is no restriction on allowed requests, the request is allowed. Likewise if the BLK_MQ_REQ_PM flag is set and the status isn't RPM_SUSPENDED. Otherwise a runtime resume is queued and the request is blocked until conditions are more suitable. [ bvanassche: modified commit message and removed Cc: stable because without the previous patches from this series this patch would break parallel SCSI domain validation + introduced queue_rpm_status() ] Link: https://lore.kernel.org/r/[email protected] Cc: Jens Axboe <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Hannes Reinecke <[email protected]> Cc: Can Guo <[email protected]> Cc: Stanley Chu <[email protected]> Cc: Ming Lei <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Reported-and-tested-by: Martin Kepplinger <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Can Guo <[email protected]> Signed-off-by: Alan Stern <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent a4d34da commit 52abca6

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

block/blk-core.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/bio.h>
1919
#include <linux/blkdev.h>
2020
#include <linux/blk-mq.h>
21+
#include <linux/blk-pm.h>
2122
#include <linux/highmem.h>
2223
#include <linux/mm.h>
2324
#include <linux/pagemap.h>
@@ -440,7 +441,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
440441
* responsible for ensuring that that counter is
441442
* globally visible before the queue is unfrozen.
442443
*/
443-
if (pm || !blk_queue_pm_only(q)) {
444+
if ((pm && queue_rpm_status(q) != RPM_SUSPENDED) ||
445+
!blk_queue_pm_only(q)) {
444446
success = true;
445447
} else {
446448
percpu_ref_put(&q->q_usage_counter);
@@ -465,8 +467,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
465467

466468
wait_event(q->mq_freeze_wq,
467469
(!q->mq_freeze_depth &&
468-
(pm || (blk_pm_request_resume(q),
469-
!blk_queue_pm_only(q)))) ||
470+
blk_pm_resume_queue(pm, q)) ||
470471
blk_queue_dying(q));
471472
if (blk_queue_dying(q))
472473
return -ENODEV;

block/blk-pm.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
#include <linux/pm_runtime.h>
77

88
#ifdef CONFIG_PM
9-
static inline void blk_pm_request_resume(struct request_queue *q)
9+
static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
1010
{
11-
if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
12-
q->rpm_status == RPM_SUSPENDING))
13-
pm_request_resume(q->dev);
11+
if (!q->dev || !blk_queue_pm_only(q))
12+
return 1; /* Nothing to do */
13+
if (pm && q->rpm_status != RPM_SUSPENDED)
14+
return 1; /* Request allowed */
15+
pm_request_resume(q->dev);
16+
return 0;
1417
}
1518

1619
static inline void blk_pm_mark_last_busy(struct request *rq)
@@ -44,8 +47,9 @@ static inline void blk_pm_put_request(struct request *rq)
4447
--rq->q->nr_pending;
4548
}
4649
#else
47-
static inline void blk_pm_request_resume(struct request_queue *q)
50+
static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
4851
{
52+
return 1;
4953
}
5054

5155
static inline void blk_pm_mark_last_busy(struct request *rq)

include/linux/blkdev.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,18 @@ static inline bool queue_is_mq(struct request_queue *q)
692692
return q->mq_ops;
693693
}
694694

695+
#ifdef CONFIG_PM
696+
static inline enum rpm_status queue_rpm_status(struct request_queue *q)
697+
{
698+
return q->rpm_status;
699+
}
700+
#else
701+
static inline enum rpm_status queue_rpm_status(struct request_queue *q)
702+
{
703+
return RPM_ACTIVE;
704+
}
705+
#endif
706+
695707
static inline enum blk_zoned_model
696708
blk_queue_zoned_model(struct request_queue *q)
697709
{

0 commit comments

Comments
 (0)