Commit ab0fd1debe730ec9998678a0c53caefbd121ed10

Authored by Tejun Heo
Committed by Jens Axboe
1 parent b59e64d0dd

block: don't merge requests of different failfast settings

Block layer used to merge requests and bios with different failfast
settings.  This caused regular IOs to fail prematurely when they were
merged into failfast requests for readahead.

Niel Lambrechts could trigger the problem semi-reliably on ext4 when
resuming from STR.  ext4 uses readahead when reading inodes and
combined with the deterministic extra SATA PHY exception cycle during
resume on the specific configuration, non-readahead inode read would
fail causing ext4 errors.  Please read the following thread for
details.

  http://lkml.org/lkml/2009/5/23/21

This patch makes block layer reject merging if the failfast settings
don't match.  This is correct but likely to lower IO performance by
preventing regular IOs from mingling into surrounding readahead
requests.  Changes to allow such mixed merges and handle errors
correctly will be added later.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Niel Lambrechts <niel.lambrechts@gmail.com>
Cc: Theodore Tso <tytso@mit.edu>
Signed-off-by: Jens Axboe <axboe@carl.(none)>

Showing 2 changed files with 14 additions and 0 deletions Side-by-side Diff

... ... @@ -350,6 +350,12 @@
350 350 if (blk_integrity_rq(req) != blk_integrity_rq(next))
351 351 return 0;
352 352  
  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 +
353 359 /*
354 360 * If we are allowed to merge, then append bio list
355 361 * from next to rq and release next. merge_requests_fn
... ... @@ -100,6 +100,14 @@
100 100 if (bio_integrity(bio) != blk_integrity_rq(rq))
101 101 return 0;
102 102  
  103 + /*
  104 + * Don't merge if failfast settings don't match
  105 + */
  106 + if (bio_failfast_dev(bio) != blk_failfast_dev(rq) ||
  107 + bio_failfast_transport(bio) != blk_failfast_transport(rq) ||
  108 + bio_failfast_driver(bio) != blk_failfast_driver(rq))
  109 + return 0;
  110 +
103 111 if (!elv_iosched_allow_merge(rq, bio))
104 112 return 0;
105 113