Skip to content

Commit 3ce6a11

Browse files
Ming Leiaxboe
authored andcommitted
block: sync mixed merged request's failfast with 1st bio's
We support mixed merge for requests/bios with different fastfail settings. When request fails, each time we only handle the portion with same failfast setting, then bios with failfast can be failed immediately, and bios without failfast can be retried. The idea is pretty good, but the current implementation has several defects: 1) initially RA bio doesn't set failfast, however bio merge code doesn't consider this point, and just check its failfast setting for deciding if mixed merge is required. Fix this issue by adding helper of bio_failfast(). 2) when merging bio to request front, if this request is mixed merged, we have to sync request's faifast setting with 1st bio's failfast. Fix it by calling blk_update_mixed_merge(). 3) when merging bio to request back, if this request is mixed merged, we have to mark the bio as failfast, because blk_update_request simply updates request failfast with 1st bio's failfast. Fix it by calling blk_update_mixed_merge(). Fixes one normal EXT4 READ IO failure issue, because it is observed that the normal READ IO is merged with RA IO, and the mixed merged request has different failfast setting with 1st bio's, so finally the normal READ IO doesn't get retried. Cc: Tejun Heo <[email protected]> Fixes: 80a761f ("block: implement mixed merge of different failfast requests") Signed-off-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent d2ad8f0 commit 3ce6a11

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

block/blk-merge.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,33 @@ void blk_rq_set_mixed_merge(struct request *rq)
757757
rq->rq_flags |= RQF_MIXED_MERGE;
758758
}
759759

760+
static inline unsigned int bio_failfast(const struct bio *bio)
761+
{
762+
if (bio->bi_opf & REQ_RAHEAD)
763+
return REQ_FAILFAST_MASK;
764+
765+
return bio->bi_opf & REQ_FAILFAST_MASK;
766+
}
767+
768+
/*
769+
* After we are marked as MIXED_MERGE, any new RA bio has to be updated
770+
* as failfast, and request's failfast has to be updated in case of
771+
* front merge.
772+
*/
773+
static inline void blk_update_mixed_merge(struct request *req,
774+
struct bio *bio, bool front_merge)
775+
{
776+
if (req->rq_flags & RQF_MIXED_MERGE) {
777+
if (bio->bi_opf & REQ_RAHEAD)
778+
bio->bi_opf |= REQ_FAILFAST_MASK;
779+
780+
if (front_merge) {
781+
req->cmd_flags &= ~REQ_FAILFAST_MASK;
782+
req->cmd_flags |= bio->bi_opf & REQ_FAILFAST_MASK;
783+
}
784+
}
785+
}
786+
760787
static void blk_account_io_merge_request(struct request *req)
761788
{
762789
if (blk_do_io_stat(req)) {
@@ -954,7 +981,7 @@ enum bio_merge_status {
954981
static enum bio_merge_status bio_attempt_back_merge(struct request *req,
955982
struct bio *bio, unsigned int nr_segs)
956983
{
957-
const blk_opf_t ff = bio->bi_opf & REQ_FAILFAST_MASK;
984+
const blk_opf_t ff = bio_failfast(bio);
958985

959986
if (!ll_back_merge_fn(req, bio, nr_segs))
960987
return BIO_MERGE_FAILED;
@@ -965,6 +992,8 @@ static enum bio_merge_status bio_attempt_back_merge(struct request *req,
965992
if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)
966993
blk_rq_set_mixed_merge(req);
967994

995+
blk_update_mixed_merge(req, bio, false);
996+
968997
req->biotail->bi_next = bio;
969998
req->biotail = bio;
970999
req->__data_len += bio->bi_iter.bi_size;
@@ -978,7 +1007,7 @@ static enum bio_merge_status bio_attempt_back_merge(struct request *req,
9781007
static enum bio_merge_status bio_attempt_front_merge(struct request *req,
9791008
struct bio *bio, unsigned int nr_segs)
9801009
{
981-
const blk_opf_t ff = bio->bi_opf & REQ_FAILFAST_MASK;
1010+
const blk_opf_t ff = bio_failfast(bio);
9821011

9831012
if (!ll_front_merge_fn(req, bio, nr_segs))
9841013
return BIO_MERGE_FAILED;
@@ -989,6 +1018,8 @@ static enum bio_merge_status bio_attempt_front_merge(struct request *req,
9891018
if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)
9901019
blk_rq_set_mixed_merge(req);
9911020

1021+
blk_update_mixed_merge(req, bio, true);
1022+
9921023
bio->bi_next = req->bio;
9931024
req->bio = bio;
9941025

0 commit comments

Comments
 (0)