Task1: ...FS.....C Task2: ....F......S...C Task3: ......F.........S..C F means a flush is queued, S means a flush is dispatched, C means the flush is completed. In above, when Task2's flush is completed, we actually can make Task3 flush complete, as Task2's flush is dispatched after Task3's flush is queued. With the same reason, we can't merge Task2 and Task3's flush with Task1's. --- block/blk-core.c | 1 + block/blk-flush.c | 24 ++++++++++++++++++++++++ include/linux/blkdev.h | 2 ++ 3 files changed, 27 insertions(+) Index: linux/block/blk-core.c =================================================================== --- linux.orig/block/blk-core.c 2011-01-13 21:02:24.000000000 +0800 +++ linux/block/blk-core.c 2011-01-13 21:43:03.000000000 +0800 @@ -128,6 +128,7 @@ void blk_rq_init(struct request_queue *q rq->ref_count = 1; rq->start_time = jiffies; set_start_time_ns(rq); + rq->next_batched_flush = NULL; } EXPORT_SYMBOL(blk_rq_init); Index: linux/block/blk-flush.c =================================================================== --- linux.orig/block/blk-flush.c 2011-01-13 21:02:24.000000000 +0800 +++ linux/block/blk-flush.c 2011-01-14 08:22:56.000000000 +0800 @@ -42,8 +42,18 @@ static struct request *blk_flush_complet /* not complete yet, queue the next flush sequence */ next_rq = queue_next_fseq(q); } else { + struct request *tmp_rq = q->orig_flush_rq->next_batched_flush; + struct request *tmp_rq2; + sector_t error_sector = q->orig_flush_rq->bio->bi_sector; + /* complete this flush request */ __blk_end_request_all(q->orig_flush_rq, q->flush_err); + while (tmp_rq) { + tmp_rq2 = tmp_rq->next_batched_flush; + tmp_rq->bio->bi_sector = error_sector; + __blk_end_request_all(tmp_rq, q->flush_err); + tmp_rq = tmp_rq2; + } q->orig_flush_rq = NULL; q->flush_seq = 0; @@ -164,6 +174,20 @@ struct request *blk_do_flush(struct requ * processing. */ if (q->flush_seq) { + struct request *tmp_rq; + + if ((rq->cmd_flags & REQ_FUA) || blk_rq_sectors(rq)) + goto add_list; + list_for_each_entry(tmp_rq, &q->pending_flushes, queuelist) { + if (tmp_rq->cmd_flags & REQ_FLUSH) { + rq->next_batched_flush = + tmp_rq->next_batched_flush; + tmp_rq->next_batched_flush = rq; + list_del_init(&rq->queuelist); + return NULL; + } + } +add_list: list_move_tail(&rq->queuelist, &q->pending_flushes); return NULL; } Index: linux/include/linux/blkdev.h =================================================================== --- linux.orig/include/linux/blkdev.h 2011-01-13 21:02:24.000000000 +0800 +++ linux/include/linux/blkdev.h 2011-01-13 21:43:03.000000000 +0800 @@ -163,6 +163,8 @@ struct request { /* for bidi */ struct request *next_rq; + + struct request *next_batched_flush; }; static inline unsigned short req_get_ioprio(struct request *req)