diff options
Diffstat (limited to 'block/blk-merge.c')
-rw-r--r-- | block/blk-merge.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index e1999679a4d5..99cb5cf1f447 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 | */ | ||
323 | void 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 | |||
314 | static void blk_account_io_merge(struct request *req) | 344 | static void blk_account_io_merge(struct request *req) |
315 | { | 345 | { |
316 | if (blk_do_io_stat(req)) { | 346 | if (blk_do_io_stat(req)) { |
@@ -321,7 +351,7 @@ static void blk_account_io_merge(struct request *req) | |||
321 | part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req)); | 351 | part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req)); |
322 | 352 | ||
323 | part_round_stats(cpu, part); | 353 | part_round_stats(cpu, part); |
324 | part_dec_in_flight(part); | 354 | part_dec_in_flight(part, rq_data_dir(req)); |
325 | 355 | ||
326 | part_stat_unlock(); | 356 | part_stat_unlock(); |
327 | } | 357 | } |
@@ -350,12 +380,6 @@ static int attempt_merge(struct request_queue *q, struct request *req, | |||
350 | if (blk_integrity_rq(req) != blk_integrity_rq(next)) | 380 | if (blk_integrity_rq(req) != blk_integrity_rq(next)) |
351 | return 0; | 381 | return 0; |
352 | 382 | ||
353 | /* don't merge requests of different failfast settings */ | ||
354 | if (blk_failfast_dev(req) != blk_failfast_dev(next) || | ||
355 | blk_failfast_transport(req) != blk_failfast_transport(next) || | ||
356 | blk_failfast_driver(req) != blk_failfast_driver(next)) | ||
357 | return 0; | ||
358 | |||
359 | /* | 383 | /* |
360 | * If we are allowed to merge, then append bio list | 384 | * If we are allowed to merge, then append bio list |
361 | * from next to rq and release next. merge_requests_fn | 385 | * from next to rq and release next. merge_requests_fn |
@@ -366,6 +390,19 @@ static int attempt_merge(struct request_queue *q, struct request *req, | |||
366 | return 0; | 390 | return 0; |
367 | 391 | ||
368 | /* | 392 | /* |
393 | * If failfast settings disagree or any of the two is already | ||
394 | * a mixed merge, mark both as mixed before proceeding. This | ||
395 | * makes sure that all involved bios have mixable attributes | ||
396 | * set properly. | ||
397 | */ | ||
398 | if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE || | ||
399 | (req->cmd_flags & REQ_FAILFAST_MASK) != | ||
400 | (next->cmd_flags & REQ_FAILFAST_MASK)) { | ||
401 | blk_rq_set_mixed_merge(req); | ||
402 | blk_rq_set_mixed_merge(next); | ||
403 | } | ||
404 | |||
405 | /* | ||
369 | * At this point we have either done a back merge | 406 | * At this point we have either done a back merge |
370 | * or front merge. We need the smaller start_time of | 407 | * or front merge. We need the smaller start_time of |
371 | * the merged requests to be the current request | 408 | * the merged requests to be the current request |