* [PATCH 1/2] block: move __elv_next_request to blk-core.c
2017-10-03 8:46 RQF_PM fix/cleanup Christoph Hellwig
@ 2017-10-03 8:47 ` Christoph Hellwig
2017-10-03 8:47 ` [PATCH 2/2] block: fix peeking requests during PM Christoph Hellwig
2017-10-03 14:43 ` RQF_PM fix/cleanup Jens Axboe
2 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2017-10-03 8:47 UTC (permalink / raw)
To: Jens Axboe; +Cc: Ming Lei, linux-block
No need to have this helper inline in a header. Also drop the __ prefix.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/blk-core.c | 42 ++++++++++++++++++++++++++++++++++++++++--
block/blk.h | 39 ---------------------------------------
2 files changed, 40 insertions(+), 41 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index 048be4aa6024..14f7674fa0b1 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2517,6 +2517,45 @@ void blk_account_io_start(struct request *rq, bool new_io)
part_stat_unlock();
}
+static struct request *elv_next_request(struct request_queue *q)
+{
+ struct request *rq;
+ struct blk_flush_queue *fq = blk_get_flush_queue(q, NULL);
+
+ WARN_ON_ONCE(q->mq_ops);
+
+ while (1) {
+ if (!list_empty(&q->queue_head)) {
+ rq = list_entry_rq(q->queue_head.next);
+ return rq;
+ }
+
+ /*
+ * Flush request is running and flush request isn't queueable
+ * in the drive, we can hold the queue till flush request is
+ * finished. Even we don't do this, driver can't dispatch next
+ * requests and will requeue them. And this can improve
+ * throughput too. For example, we have request flush1, write1,
+ * flush 2. flush1 is dispatched, then queue is hold, write1
+ * isn't inserted to queue. After flush1 is finished, flush2
+ * will be dispatched. Since disk cache is already clean,
+ * flush2 will be finished very soon, so looks like flush2 is
+ * folded to flush1.
+ * Since the queue is hold, a flag is set to indicate the queue
+ * should be restarted later. Please see flush_end_io() for
+ * details.
+ */
+ if (fq->flush_pending_idx != fq->flush_running_idx &&
+ !queue_flush_queueable(q)) {
+ fq->flush_queue_delayed = 1;
+ return NULL;
+ }
+ if (unlikely(blk_queue_bypass(q)) ||
+ !q->elevator->type->ops.sq.elevator_dispatch_fn(q, 0))
+ return NULL;
+ }
+}
+
/**
* blk_peek_request - peek at the top of a request queue
* @q: request queue to peek at
@@ -2538,8 +2577,7 @@ struct request *blk_peek_request(struct request_queue *q)
lockdep_assert_held(q->queue_lock);
WARN_ON_ONCE(q->mq_ops);
- while ((rq = __elv_next_request(q)) != NULL) {
-
+ while ((rq = elv_next_request(q)) != NULL) {
rq = blk_pm_peek_request(q, rq);
if (!rq)
break;
diff --git a/block/blk.h b/block/blk.h
index fcb9775b997d..fda5a4632aba 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -148,45 +148,6 @@ static inline void blk_clear_rq_complete(struct request *rq)
void blk_insert_flush(struct request *rq);
-static inline struct request *__elv_next_request(struct request_queue *q)
-{
- struct request *rq;
- struct blk_flush_queue *fq = blk_get_flush_queue(q, NULL);
-
- WARN_ON_ONCE(q->mq_ops);
-
- while (1) {
- if (!list_empty(&q->queue_head)) {
- rq = list_entry_rq(q->queue_head.next);
- return rq;
- }
-
- /*
- * Flush request is running and flush request isn't queueable
- * in the drive, we can hold the queue till flush request is
- * finished. Even we don't do this, driver can't dispatch next
- * requests and will requeue them. And this can improve
- * throughput too. For example, we have request flush1, write1,
- * flush 2. flush1 is dispatched, then queue is hold, write1
- * isn't inserted to queue. After flush1 is finished, flush2
- * will be dispatched. Since disk cache is already clean,
- * flush2 will be finished very soon, so looks like flush2 is
- * folded to flush1.
- * Since the queue is hold, a flag is set to indicate the queue
- * should be restarted later. Please see flush_end_io() for
- * details.
- */
- if (fq->flush_pending_idx != fq->flush_running_idx &&
- !queue_flush_queueable(q)) {
- fq->flush_queue_delayed = 1;
- return NULL;
- }
- if (unlikely(blk_queue_bypass(q)) ||
- !q->elevator->type->ops.sq.elevator_dispatch_fn(q, 0))
- return NULL;
- }
-}
-
static inline void elv_activate_rq(struct request_queue *q, struct request *rq)
{
struct elevator_queue *e = q->elevator;
--
2.14.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/2] block: fix peeking requests during PM
2017-10-03 8:46 RQF_PM fix/cleanup Christoph Hellwig
2017-10-03 8:47 ` [PATCH 1/2] block: move __elv_next_request to blk-core.c Christoph Hellwig
@ 2017-10-03 8:47 ` Christoph Hellwig
2017-10-03 15:13 ` Bart Van Assche
2017-10-03 14:43 ` RQF_PM fix/cleanup Jens Axboe
2 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2017-10-03 8:47 UTC (permalink / raw)
To: Jens Axboe; +Cc: Ming Lei, linux-block
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>
---
block/blk-core.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index 14f7674fa0b1..2b704759913a 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2464,20 +2464,24 @@ 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;
+ if (!rq->q->dev)
+ return true;
+
+ switch (rq->q->rpm_status) {
+ case RPM_SUSPENDED:
+ return false;
+ case RPM_ACTIVE:
+ return rq->rq_flags & RQF_PM;
+ default:
+ 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
@@ -2525,9 +2529,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;
}
/*
@@ -2578,10 +2585,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
--
2.14.1
^ permalink raw reply related [flat|nested] 6+ messages in thread