summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-flush.c10
-rw-r--r--block/blk-mq.c5
-rw-r--r--block/blk.h7
3 files changed, 21 insertions, 1 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c
index aedd9320e605..1eec9cbe5a0a 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -214,6 +214,16 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
214 214
215 /* release the tag's ownership to the req cloned from */ 215 /* release the tag's ownership to the req cloned from */
216 spin_lock_irqsave(&fq->mq_flush_lock, flags); 216 spin_lock_irqsave(&fq->mq_flush_lock, flags);
217
218 if (!refcount_dec_and_test(&flush_rq->ref)) {
219 fq->rq_status = error;
220 spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
221 return;
222 }
223
224 if (fq->rq_status != BLK_STS_OK)
225 error = fq->rq_status;
226
217 hctx = flush_rq->mq_hctx; 227 hctx = flush_rq->mq_hctx;
218 if (!q->elevator) { 228 if (!q->elevator) {
219 blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq); 229 blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 29275f5a996f..6e3b15f70cd7 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -918,7 +918,10 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
918 */ 918 */
919 if (blk_mq_req_expired(rq, next)) 919 if (blk_mq_req_expired(rq, next))
920 blk_mq_rq_timed_out(rq, reserved); 920 blk_mq_rq_timed_out(rq, reserved);
921 if (refcount_dec_and_test(&rq->ref)) 921
922 if (is_flush_rq(rq, hctx))
923 rq->end_io(rq, 0);
924 else if (refcount_dec_and_test(&rq->ref))
922 __blk_mq_free_request(rq); 925 __blk_mq_free_request(rq);
923 926
924 return true; 927 return true;
diff --git a/block/blk.h b/block/blk.h
index 25773d668ec0..47fba9362e60 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -19,6 +19,7 @@ struct blk_flush_queue {
19 unsigned int flush_queue_delayed:1; 19 unsigned int flush_queue_delayed:1;
20 unsigned int flush_pending_idx:1; 20 unsigned int flush_pending_idx:1;
21 unsigned int flush_running_idx:1; 21 unsigned int flush_running_idx:1;
22 blk_status_t rq_status;
22 unsigned long flush_pending_since; 23 unsigned long flush_pending_since;
23 struct list_head flush_queue[2]; 24 struct list_head flush_queue[2];
24 struct list_head flush_data_in_flight; 25 struct list_head flush_data_in_flight;
@@ -47,6 +48,12 @@ static inline void __blk_get_queue(struct request_queue *q)
47 kobject_get(&q->kobj); 48 kobject_get(&q->kobj);
48} 49}
49 50
51static inline bool
52is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx)
53{
54 return hctx->fq->flush_rq == req;
55}
56
50struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q, 57struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q,
51 int node, int cmd_size, gfp_t flags); 58 int node, int cmd_size, gfp_t flags);
52void blk_free_flush_queue(struct blk_flush_queue *q); 59void blk_free_flush_queue(struct blk_flush_queue *q);