aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-core.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-01-25 06:43:54 -0500
committerJens Axboe <jaxboe@fusionio.com>2011-01-25 06:43:54 -0500
commitae1b1539622fb46e51b4d13b3f9e5f4c713f86ae (patch)
treec5cb540141003a3ec7ebf0b8c6e01653ab6aaef5 /block/blk-core.c
parent143a87f4c9c629067afea5b6703d66ea88c82f8e (diff)
block: reimplement FLUSH/FUA to support merge
The current FLUSH/FUA support has evolved from the implementation which had to perform queue draining. As such, sequencing is done queue-wide one flush request after another. However, with the draining requirement gone, there's no reason to keep the queue-wide sequential approach. This patch reimplements FLUSH/FUA support such that each FLUSH/FUA request is sequenced individually. The actual FLUSH execution is double buffered and whenever a request wants to execute one for either PRE or POSTFLUSH, it queues on the pending queue. Once certain conditions are met, a flush request is issued and on its completion all pending requests proceed to the next sequence. This allows arbitrary merging of different type of flushes. How they are merged can be primarily controlled and tuned by adjusting the above said 'conditions' used to determine when to issue the next flush. This is inspired by Darrick's patches to merge multiple zero-data flushes which helps workloads with highly concurrent fsync requests. * As flush requests are never put on the IO scheduler, request fields used for flush share space with rq->rb_node. rq->completion_data is moved out of the union. This increases the request size by one pointer. As rq->elevator_private* are used only by the iosched too, it is possible to reduce the request size further. However, to do that, we need to modify request allocation path such that iosched data is not allocated for flush requests. * FLUSH/FUA processing happens on insertion now instead of dispatch. - Comments updated as per Vivek and Mike. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: "Darrick J. Wong" <djwong@us.ibm.com> Cc: Shaohua Li <shli@kernel.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block/blk-core.c')
-rw-r--r--block/blk-core.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 617bb9e40927..05746093b45e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -134,8 +134,6 @@ EXPORT_SYMBOL(blk_rq_init);
134static void req_bio_endio(struct request *rq, struct bio *bio, 134static void req_bio_endio(struct request *rq, struct bio *bio,
135 unsigned int nbytes, int error) 135 unsigned int nbytes, int error)
136{ 136{
137 struct request_queue *q = rq->q;
138
139 if (error) 137 if (error)
140 clear_bit(BIO_UPTODATE, &bio->bi_flags); 138 clear_bit(BIO_UPTODATE, &bio->bi_flags);
141 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) 139 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
@@ -159,8 +157,6 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
159 /* don't actually finish bio if it's part of flush sequence */ 157 /* don't actually finish bio if it's part of flush sequence */
160 if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) 158 if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
161 bio_endio(bio, error); 159 bio_endio(bio, error);
162 else if (error && !q->flush_err)
163 q->flush_err = error;
164} 160}
165 161
166void blk_dump_rq_flags(struct request *rq, char *msg) 162void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -519,7 +515,9 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
519 init_timer(&q->unplug_timer); 515 init_timer(&q->unplug_timer);
520 setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); 516 setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
521 INIT_LIST_HEAD(&q->timeout_list); 517 INIT_LIST_HEAD(&q->timeout_list);
522 INIT_LIST_HEAD(&q->pending_flushes); 518 INIT_LIST_HEAD(&q->flush_queue[0]);
519 INIT_LIST_HEAD(&q->flush_queue[1]);
520 INIT_LIST_HEAD(&q->flush_data_in_flight);
523 INIT_WORK(&q->unplug_work, blk_unplug_work); 521 INIT_WORK(&q->unplug_work, blk_unplug_work);
524 522
525 kobject_init(&q->kobj, &blk_queue_ktype); 523 kobject_init(&q->kobj, &blk_queue_ktype);
@@ -1198,7 +1196,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
1198 spin_lock_irq(q->queue_lock); 1196 spin_lock_irq(q->queue_lock);
1199 1197
1200 if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { 1198 if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
1201 where = ELEVATOR_INSERT_FRONT; 1199 where = ELEVATOR_INSERT_FLUSH;
1202 goto get_rq; 1200 goto get_rq;
1203 } 1201 }
1204 1202