summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaohua Li <shli@kernel.org>2014-05-30 08:06:42 -0600
committerJens Axboe <axboe@fb.com>2014-05-30 08:06:42 -0600
commit2230237500821aedfcf2bba2a79d9cbca389233c (patch)
treeb4b7bee385293f8cc318fb309909ca3e701b903b
parentda52f22fa924b4a21d8e11fbfd3eeebd7a90a366 (diff)
downloadlinux-2230237500821aedfcf2bba2a79d9cbca389233c.tar.bz2
blk-mq: blk_mq_tag_to_rq should handle flush request
flush request is special, which borrows the tag from the parent request. Hence blk_mq_tag_to_rq needs special handling to return the flush request from the tag. Signed-off-by: Shaohua Li <shli@fusionio.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-flush.c4
-rw-r--r--block/blk-mq.c12
-rw-r--r--include/linux/blk-mq.h2
3 files changed, 13 insertions, 5 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c
index ef608b35d9be..ff87c664b7df 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -223,8 +223,10 @@ static void flush_end_io(struct request *flush_rq, int error)
struct request *rq, *n;
unsigned long flags = 0;
- if (q->mq_ops)
+ if (q->mq_ops) {
spin_lock_irqsave(&q->mq_flush_lock, flags);
+ q->flush_rq->cmd_flags = 0;
+ }
running = &q->flush_queue[q->flush_running_idx];
BUG_ON(q->flush_pending_idx == q->flush_running_idx);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 6160128085fc..21f952ab3581 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -541,9 +541,15 @@ void blk_mq_kick_requeue_list(struct request_queue *q)
}
EXPORT_SYMBOL(blk_mq_kick_requeue_list);
-struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
+struct request *blk_mq_tag_to_rq(struct blk_mq_hw_ctx *hctx, unsigned int tag)
{
- return tags->rqs[tag];
+ struct request_queue *q = hctx->queue;
+
+ if ((q->flush_rq->cmd_flags & REQ_FLUSH_SEQ) &&
+ q->flush_rq->tag == tag)
+ return q->flush_rq;
+
+ return hctx->tags->rqs[tag];
}
EXPORT_SYMBOL(blk_mq_tag_to_rq);
@@ -572,7 +578,7 @@ static void blk_mq_timeout_check(void *__data, unsigned long *free_tags)
if (tag >= hctx->tags->nr_tags)
break;
- rq = blk_mq_tag_to_rq(hctx->tags, tag++);
+ rq = blk_mq_tag_to_rq(hctx, tag++);
if (rq->q != hctx->queue)
continue;
if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags))
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 95de239444d2..ad3adb73cc70 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -154,7 +154,7 @@ void blk_mq_free_request(struct request *rq);
bool blk_mq_can_queue(struct blk_mq_hw_ctx *);
struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
gfp_t gfp, bool reserved);
-struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag);
+struct request *blk_mq_tag_to_rq(struct blk_mq_hw_ctx *hctx, unsigned int tag);
struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index);
struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int);