summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-10-20 16:45:23 +0200
committerJens Axboe <axboe@kernel.dk>2017-11-04 08:17:06 -0600
commite4f36b249b4d4e7599f1cf0c8fb50f196e52677e (patch)
tree9416b12f2289b8cf9842a28db15e247c5c00987a
parent21e768b442bb587123ea924620e74d6e5655d717 (diff)
downloadlwn-e4f36b249b4d4e7599f1cf0c8fb50f196e52677e.tar.gz
lwn-e4f36b249b4d4e7599f1cf0c8fb50f196e52677e.zip
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.c35
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