aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-merge.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-07-03 04:48:17 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-09-11 08:33:30 -0400
commit80a761fd33cf812f771e212139157bf8f58d4b3f (patch)
tree21ea67ad749c15f25cb8a9278fe9bd7643c0ba31 /block/blk-merge.c
parenta82afdfcb8c0df09776b6458af6b68fc58b2e87b (diff)
block: implement mixed merge of different failfast requests
Failfast has characteristics from other attributes. When issuing, executing and successuflly completing requests, failfast doesn't make any difference. It only affects how a request is handled on failure. Allowing requests with different failfast settings to be merged cause normal IOs to fail prematurely while not allowing has performance penalties as failfast is used for read aheads which are likely to be located near in-flight or to-be-issued normal IOs. This patch introduces the concept of 'mixed merge'. A request is a mixed merge if it is merge of segments which require different handling on failure. Currently the only mixable attributes are failfast ones (or lack thereof). When a bio with different failfast settings is added to an existing request or requests of different failfast settings are merged, the merged request is marked mixed. Each bio carries failfast settings and the request always tracks failfast state of the first bio. When the request fails, blk_rq_err_bytes() can be used to determine how many bytes can be safely failed without crossing into an area which requires further retrials. This allows request merging regardless of failfast settings while keeping the failure handling correct. This patch only implements mixed merge but doesn't enable it. The next one will update SCSI to make use of mixed merge. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Niel Lambrechts <niel.lambrechts@gmail.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/blk-merge.c')
-rw-r--r--block/blk-merge.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c
index e1999679a4d5..7c9ca01baa45 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -311,6 +311,36 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
311 return 1; 311 return 1;
312} 312}
313 313
314/**
315 * blk_rq_set_mixed_merge - mark a request as mixed merge
316 * @rq: request to mark as mixed merge
317 *
318 * Description:
319 * @rq is about to be mixed merged. Make sure the attributes
320 * which can be mixed are set in each bio and mark @rq as mixed
321 * merged.
322 */
323void blk_rq_set_mixed_merge(struct request *rq)
324{
325 unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK;
326 struct bio *bio;
327
328 if (rq->cmd_flags & REQ_MIXED_MERGE)
329 return;
330
331 /*
332 * @rq will no longer represent mixable attributes for all the
333 * contained bios. It will just track those of the first one.
334 * Distributes the attributs to each bio.
335 */
336 for (bio = rq->bio; bio; bio = bio->bi_next) {
337 WARN_ON_ONCE((bio->bi_rw & REQ_FAILFAST_MASK) &&
338 (bio->bi_rw & REQ_FAILFAST_MASK) != ff);
339 bio->bi_rw |= ff;
340 }
341 rq->cmd_flags |= REQ_MIXED_MERGE;
342}
343
314static void blk_account_io_merge(struct request *req) 344static void blk_account_io_merge(struct request *req)
315{ 345{
316 if (blk_do_io_stat(req)) { 346 if (blk_do_io_stat(req)) {
@@ -366,6 +396,19 @@ static int attempt_merge(struct request_queue *q, struct request *req,
366 return 0; 396 return 0;
367 397
368 /* 398 /*
399 * If failfast settings disagree or any of the two is already
400 * a mixed merge, mark both as mixed before proceeding. This
401 * makes sure that all involved bios have mixable attributes
402 * set properly.
403 */
404 if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE ||
405 (req->cmd_flags & REQ_FAILFAST_MASK) !=
406 (next->cmd_flags & REQ_FAILFAST_MASK)) {
407 blk_rq_set_mixed_merge(req);
408 blk_rq_set_mixed_merge(next);
409 }
410
411 /*
369 * At this point we have either done a back merge 412 * At this point we have either done a back merge
370 * or front merge. We need the smaller start_time of 413 * or front merge. We need the smaller start_time of
371 * the merged requests to be the current request 414 * the merged requests to be the current request