diff options
-rw-r--r-- | block/blk-core.c | 8 | ||||
-rw-r--r-- | block/blk-flush.c | 20 | ||||
-rw-r--r-- | block/blk.h | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 1 |
4 files changed, 25 insertions, 6 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index b850bedad229..7c59b0f5eae8 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1700,6 +1700,7 @@ EXPORT_SYMBOL_GPL(blk_rq_check_limits); | |||
1700 | int blk_insert_cloned_request(struct request_queue *q, struct request *rq) | 1700 | int blk_insert_cloned_request(struct request_queue *q, struct request *rq) |
1701 | { | 1701 | { |
1702 | unsigned long flags; | 1702 | unsigned long flags; |
1703 | int where = ELEVATOR_INSERT_BACK; | ||
1703 | 1704 | ||
1704 | if (blk_rq_check_limits(q, rq)) | 1705 | if (blk_rq_check_limits(q, rq)) |
1705 | return -EIO; | 1706 | return -EIO; |
@@ -1716,7 +1717,10 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) | |||
1716 | */ | 1717 | */ |
1717 | BUG_ON(blk_queued_rq(rq)); | 1718 | BUG_ON(blk_queued_rq(rq)); |
1718 | 1719 | ||
1719 | add_acct_request(q, rq, ELEVATOR_INSERT_BACK); | 1720 | if (rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) |
1721 | where = ELEVATOR_INSERT_FLUSH; | ||
1722 | |||
1723 | add_acct_request(q, rq, where); | ||
1720 | spin_unlock_irqrestore(q->queue_lock, flags); | 1724 | spin_unlock_irqrestore(q->queue_lock, flags); |
1721 | 1725 | ||
1722 | return 0; | 1726 | return 0; |
@@ -2273,7 +2277,7 @@ static bool blk_end_bidi_request(struct request *rq, int error, | |||
2273 | * %false - we are done with this request | 2277 | * %false - we are done with this request |
2274 | * %true - still buffers pending for this request | 2278 | * %true - still buffers pending for this request |
2275 | **/ | 2279 | **/ |
2276 | static bool __blk_end_bidi_request(struct request *rq, int error, | 2280 | bool __blk_end_bidi_request(struct request *rq, int error, |
2277 | unsigned int nr_bytes, unsigned int bidi_bytes) | 2281 | unsigned int nr_bytes, unsigned int bidi_bytes) |
2278 | { | 2282 | { |
2279 | if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes)) | 2283 | if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes)) |
diff --git a/block/blk-flush.c b/block/blk-flush.c index 2d162bd840d3..491eb30a242d 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c | |||
@@ -123,7 +123,7 @@ static void blk_flush_restore_request(struct request *rq) | |||
123 | 123 | ||
124 | /* make @rq a normal request */ | 124 | /* make @rq a normal request */ |
125 | rq->cmd_flags &= ~REQ_FLUSH_SEQ; | 125 | rq->cmd_flags &= ~REQ_FLUSH_SEQ; |
126 | rq->end_io = NULL; | 126 | rq->end_io = rq->flush.saved_end_io; |
127 | } | 127 | } |
128 | 128 | ||
129 | /** | 129 | /** |
@@ -301,9 +301,6 @@ void blk_insert_flush(struct request *rq) | |||
301 | unsigned int fflags = q->flush_flags; /* may change, cache */ | 301 | unsigned int fflags = q->flush_flags; /* may change, cache */ |
302 | unsigned int policy = blk_flush_policy(fflags, rq); | 302 | unsigned int policy = blk_flush_policy(fflags, rq); |
303 | 303 | ||
304 | BUG_ON(rq->end_io); | ||
305 | BUG_ON(!rq->bio || rq->bio != rq->biotail); | ||
306 | |||
307 | /* | 304 | /* |
308 | * @policy now records what operations need to be done. Adjust | 305 | * @policy now records what operations need to be done. Adjust |
309 | * REQ_FLUSH and FUA for the driver. | 306 | * REQ_FLUSH and FUA for the driver. |
@@ -313,6 +310,19 @@ void blk_insert_flush(struct request *rq) | |||
313 | rq->cmd_flags &= ~REQ_FUA; | 310 | rq->cmd_flags &= ~REQ_FUA; |
314 | 311 | ||
315 | /* | 312 | /* |
313 | * An empty flush handed down from a stacking driver may | ||
314 | * translate into nothing if the underlying device does not | ||
315 | * advertise a write-back cache. In this case, simply | ||
316 | * complete the request. | ||
317 | */ | ||
318 | if (!policy) { | ||
319 | __blk_end_bidi_request(rq, 0, 0, 0); | ||
320 | return; | ||
321 | } | ||
322 | |||
323 | BUG_ON(!rq->bio || rq->bio != rq->biotail); | ||
324 | |||
325 | /* | ||
316 | * If there's data but flush is not necessary, the request can be | 326 | * If there's data but flush is not necessary, the request can be |
317 | * processed directly without going through flush machinery. Queue | 327 | * processed directly without going through flush machinery. Queue |
318 | * for normal execution. | 328 | * for normal execution. |
@@ -320,6 +330,7 @@ void blk_insert_flush(struct request *rq) | |||
320 | if ((policy & REQ_FSEQ_DATA) && | 330 | if ((policy & REQ_FSEQ_DATA) && |
321 | !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { | 331 | !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { |
322 | list_add_tail(&rq->queuelist, &q->queue_head); | 332 | list_add_tail(&rq->queuelist, &q->queue_head); |
333 | blk_run_queue_async(q); | ||
323 | return; | 334 | return; |
324 | } | 335 | } |
325 | 336 | ||
@@ -330,6 +341,7 @@ void blk_insert_flush(struct request *rq) | |||
330 | memset(&rq->flush, 0, sizeof(rq->flush)); | 341 | memset(&rq->flush, 0, sizeof(rq->flush)); |
331 | INIT_LIST_HEAD(&rq->flush.list); | 342 | INIT_LIST_HEAD(&rq->flush.list); |
332 | rq->cmd_flags |= REQ_FLUSH_SEQ; | 343 | rq->cmd_flags |= REQ_FLUSH_SEQ; |
344 | rq->flush.saved_end_io = rq->end_io; /* Usually NULL */ | ||
333 | rq->end_io = flush_data_end_io; | 345 | rq->end_io = flush_data_end_io; |
334 | 346 | ||
335 | blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0); | 347 | blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0); |
diff --git a/block/blk.h b/block/blk.h index d6586287adc9..20b900a377c9 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -17,6 +17,8 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq, | |||
17 | struct bio *bio); | 17 | struct bio *bio); |
18 | void blk_dequeue_request(struct request *rq); | 18 | void blk_dequeue_request(struct request *rq); |
19 | void __blk_queue_free_tags(struct request_queue *q); | 19 | void __blk_queue_free_tags(struct request_queue *q); |
20 | bool __blk_end_bidi_request(struct request *rq, int error, | ||
21 | unsigned int nr_bytes, unsigned int bidi_bytes); | ||
20 | 22 | ||
21 | void blk_rq_timed_out_timer(unsigned long data); | 23 | void blk_rq_timed_out_timer(unsigned long data); |
22 | void blk_delete_timer(struct request *); | 24 | void blk_delete_timer(struct request *); |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 847928546076..84b15d54f8c2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -118,6 +118,7 @@ struct request { | |||
118 | struct { | 118 | struct { |
119 | unsigned int seq; | 119 | unsigned int seq; |
120 | struct list_head list; | 120 | struct list_head list; |
121 | rq_end_io_fn *saved_end_io; | ||
121 | } flush; | 122 | } flush; |
122 | }; | 123 | }; |
123 | 124 | ||