summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-flush.c15
-rw-r--r--block/blk-mq-tag.c4
-rw-r--r--block/blk-mq-tag.h12
-rw-r--r--block/blk-mq.c16
-rw-r--r--block/blk.h6
5 files changed, 35 insertions, 18 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 20badd7b9d1b..9c423e53324a 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -73,6 +73,7 @@
73 73
74#include "blk.h" 74#include "blk.h"
75#include "blk-mq.h" 75#include "blk-mq.h"
76#include "blk-mq-tag.h"
76 77
77/* FLUSH/FUA sequences */ 78/* FLUSH/FUA sequences */
78enum { 79enum {
@@ -226,7 +227,12 @@ static void flush_end_io(struct request *flush_rq, int error)
226 struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx); 227 struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx);
227 228
228 if (q->mq_ops) { 229 if (q->mq_ops) {
230 struct blk_mq_hw_ctx *hctx;
231
232 /* release the tag's ownership to the req cloned from */
229 spin_lock_irqsave(&fq->mq_flush_lock, flags); 233 spin_lock_irqsave(&fq->mq_flush_lock, flags);
234 hctx = q->mq_ops->map_queue(q, flush_rq->mq_ctx->cpu);
235 blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq);
230 flush_rq->tag = -1; 236 flush_rq->tag = -1;
231 } 237 }
232 238
@@ -308,11 +314,18 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
308 314
309 /* 315 /*
310 * Borrow tag from the first request since they can't 316 * Borrow tag from the first request since they can't
311 * be in flight at the same time. 317 * be in flight at the same time. And acquire the tag's
318 * ownership for flush req.
312 */ 319 */
313 if (q->mq_ops) { 320 if (q->mq_ops) {
321 struct blk_mq_hw_ctx *hctx;
322
314 flush_rq->mq_ctx = first_rq->mq_ctx; 323 flush_rq->mq_ctx = first_rq->mq_ctx;
315 flush_rq->tag = first_rq->tag; 324 flush_rq->tag = first_rq->tag;
325 fq->orig_rq = first_rq;
326
327 hctx = q->mq_ops->map_queue(q, first_rq->mq_ctx->cpu);
328 blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq);
316 } 329 }
317 330
318 flush_rq->cmd_type = REQ_TYPE_FS; 331 flush_rq->cmd_type = REQ_TYPE_FS;
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 9b6e28830b82..9115c6d59948 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -429,7 +429,7 @@ static void bt_for_each(struct blk_mq_hw_ctx *hctx,
429 for (bit = find_first_bit(&bm->word, bm->depth); 429 for (bit = find_first_bit(&bm->word, bm->depth);
430 bit < bm->depth; 430 bit < bm->depth;
431 bit = find_next_bit(&bm->word, bm->depth, bit + 1)) { 431 bit = find_next_bit(&bm->word, bm->depth, bit + 1)) {
432 rq = blk_mq_tag_to_rq(hctx->tags, off + bit); 432 rq = hctx->tags->rqs[off + bit];
433 if (rq->q == hctx->queue) 433 if (rq->q == hctx->queue)
434 fn(hctx, rq, data, reserved); 434 fn(hctx, rq, data, reserved);
435 } 435 }
@@ -453,7 +453,7 @@ static void bt_tags_for_each(struct blk_mq_tags *tags,
453 for (bit = find_first_bit(&bm->word, bm->depth); 453 for (bit = find_first_bit(&bm->word, bm->depth);
454 bit < bm->depth; 454 bit < bm->depth;
455 bit = find_next_bit(&bm->word, bm->depth, bit + 1)) { 455 bit = find_next_bit(&bm->word, bm->depth, bit + 1)) {
456 rq = blk_mq_tag_to_rq(tags, off + bit); 456 rq = tags->rqs[off + bit];
457 fn(rq, data, reserved); 457 fn(rq, data, reserved);
458 } 458 }
459 459
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
index 75893a34237d..9eb2cf4f01cb 100644
--- a/block/blk-mq-tag.h
+++ b/block/blk-mq-tag.h
@@ -89,4 +89,16 @@ static inline void blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx)
89 __blk_mq_tag_idle(hctx); 89 __blk_mq_tag_idle(hctx);
90} 90}
91 91
92/*
93 * This helper should only be used for flush request to share tag
94 * with the request cloned from, and both the two requests can't be
95 * in flight at the same time. The caller has to make sure the tag
96 * can't be freed.
97 */
98static inline void blk_mq_tag_set_rq(struct blk_mq_hw_ctx *hctx,
99 unsigned int tag, struct request *rq)
100{
101 hctx->tags->rqs[tag] = rq;
102}
103
92#endif 104#endif
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 81edbd95bda8..f2d67b4047a0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -559,23 +559,9 @@ void blk_mq_abort_requeue_list(struct request_queue *q)
559} 559}
560EXPORT_SYMBOL(blk_mq_abort_requeue_list); 560EXPORT_SYMBOL(blk_mq_abort_requeue_list);
561 561
562static inline bool is_flush_request(struct request *rq,
563 struct blk_flush_queue *fq, unsigned int tag)
564{
565 return ((rq->cmd_flags & REQ_FLUSH_SEQ) &&
566 fq->flush_rq->tag == tag);
567}
568
569struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag) 562struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
570{ 563{
571 struct request *rq = tags->rqs[tag]; 564 return tags->rqs[tag];
572 /* mq_ctx of flush rq is always cloned from the corresponding req */
573 struct blk_flush_queue *fq = blk_get_flush_queue(rq->q, rq->mq_ctx);
574
575 if (!is_flush_request(rq, fq, tag))
576 return rq;
577
578 return fq->flush_rq;
579} 565}
580EXPORT_SYMBOL(blk_mq_tag_to_rq); 566EXPORT_SYMBOL(blk_mq_tag_to_rq);
581 567
diff --git a/block/blk.h b/block/blk.h
index 026d9594142b..838188b35a83 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -22,6 +22,12 @@ struct blk_flush_queue {
22 struct list_head flush_queue[2]; 22 struct list_head flush_queue[2];
23 struct list_head flush_data_in_flight; 23 struct list_head flush_data_in_flight;
24 struct request *flush_rq; 24 struct request *flush_rq;
25
26 /*
27 * flush_rq shares tag with this rq, both can't be active
28 * at the same time
29 */
30 struct request *orig_rq;
25 spinlock_t mq_flush_lock; 31 spinlock_t mq_flush_lock;
26}; 32};
27 33