diff options
-rw-r--r-- | block/blk-flush.c | 10 | ||||
-rw-r--r-- | block/blk-mq.c | 5 | ||||
-rw-r--r-- | block/blk.h | 7 |
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 | ||
51 | static inline bool | ||
52 | is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx) | ||
53 | { | ||
54 | return hctx->fq->flush_rq == req; | ||
55 | } | ||
56 | |||
50 | struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q, | 57 | struct 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); |
52 | void blk_free_flush_queue(struct blk_flush_queue *q); | 59 | void blk_free_flush_queue(struct blk_flush_queue *q); |