diff options
author | Christoph Hellwig <hch@lst.de> | 2017-10-20 16:45:23 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2017-11-04 08:17:06 -0600 |
commit | e4f36b249b4d4e7599f1cf0c8fb50f196e52677e (patch) | |
tree | 9416b12f2289b8cf9842a28db15e247c5c00987a | |
parent | 21e768b442bb587123ea924620e74d6e5655d717 (diff) |
block: fix peeking requests during PM
We need to look for an active PM request until the next softbarrier
instead of looking for the first non-PM request. Otherwise any cause
of request reordering might starve the PM request(s).
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | block/blk-core.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 395bfb10d658..223f32826e62 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2511,20 +2511,22 @@ void blk_account_io_done(struct request *req) * Don't process normal requests when queue is suspended * or in the process of suspending/resuming */ -static struct request *blk_pm_peek_request(struct request_queue *q, - struct request *rq) +static bool blk_pm_allow_request(struct request *rq) { - if (q->dev && (q->rpm_status == RPM_SUSPENDED || - (q->rpm_status != RPM_ACTIVE && !(rq->rq_flags & RQF_PM)))) - return NULL; - else - return rq; + switch (rq->q->rpm_status) { + case RPM_RESUMING: + case RPM_SUSPENDING: + return rq->rq_flags & RQF_PM; + case RPM_SUSPENDED: + return false; + } + + return true; } #else -static inline struct request *blk_pm_peek_request(struct request_queue *q, - struct request *rq) +static bool blk_pm_allow_request(struct request *rq) { - return rq; + return true; } #endif @@ -2572,9 +2574,12 @@ static struct request *elv_next_request(struct request_queue *q) WARN_ON_ONCE(q->mq_ops); while (1) { - if (!list_empty(&q->queue_head)) { - rq = list_entry_rq(q->queue_head.next); - return rq; + list_for_each_entry(rq, &q->queue_head, queuelist) { + if (blk_pm_allow_request(rq)) + return rq; + + if (rq->rq_flags & RQF_SOFTBARRIER) + break; } /* @@ -2625,10 +2630,6 @@ struct request *blk_peek_request(struct request_queue *q) WARN_ON_ONCE(q->mq_ops); while ((rq = elv_next_request(q)) != NULL) { - rq = blk_pm_peek_request(q, rq); - if (!rq) - break; - if (!(rq->rq_flags & RQF_STARTED)) { /* * This is the first time the device driver |