From: Yu Kuai On the one hand unify bio split code, prepare to fix disordered split IO; On the other hand fix missing blkcg_bio_issue_init() and trace_block_split() for split IO. Noted discard is not handled, because discard is only splited for unaligned head and tail. Signed-off-by: Yu Kuai --- drivers/md/raid10.c | 53 ++++++++++++++++++++------------------------- drivers/md/raid10.h | 1 + 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b60c30bfb6c7..b8777661307b 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -322,10 +322,12 @@ static void raid_end_bio_io(struct r10bio *r10_bio) struct bio *bio = r10_bio->master_bio; struct r10conf *conf = r10_bio->mddev->private; - if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) - bio->bi_status = BLK_STS_IOERR; + if (!test_and_set_bit(R10BIO_Returned, &r10_bio->state)) { + if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) + bio->bi_status = BLK_STS_IOERR; + bio_endio(bio); + } - bio_endio(bio); /* * Wake up any possible resync thread that waits for the device * to go idle. @@ -1154,7 +1156,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, int slot = r10_bio->read_slot; struct md_rdev *err_rdev = NULL; gfp_t gfp = GFP_NOIO; - int error; if (slot >= 0 && r10_bio->devs[slot].rdev) { /* @@ -1203,17 +1204,16 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, rdev->bdev, (unsigned long long)r10_bio->sector); if (max_sectors < bio_sectors(bio)) { - struct bio *split = bio_split(bio, max_sectors, - gfp, &conf->bio_split); - if (IS_ERR(split)) { - error = PTR_ERR(split); - goto err_handle; - } - bio_chain(split, bio); allow_barrier(conf); - submit_bio_noacct(bio); + bio = bio_submit_split(bio, max_sectors, &conf->bio_split); wait_barrier(conf, false); - bio = split; + + if (!bio) { + set_bit(R10BIO_Returned, &r10_bio->state); + goto err_handle; + } + + bio->bi_opf &= ~REQ_NOMERGE; r10_bio->master_bio = bio; r10_bio->sectors = max_sectors; } @@ -1239,10 +1239,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, mddev_trace_remap(mddev, read_bio, r10_bio->sector); submit_bio_noacct(read_bio); return; + err_handle: atomic_dec(&rdev->nr_pending); - bio->bi_status = errno_to_blk_status(error); - set_bit(R10BIO_Uptodate, &r10_bio->state); raid_end_bio_io(r10_bio); } @@ -1351,7 +1350,6 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, int i, k; sector_t sectors; int max_sectors; - int error; if ((mddev_is_clustered(mddev) && mddev->cluster_ops->area_resyncing(mddev, WRITE, @@ -1465,10 +1463,8 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, * complexity of supporting that is not worth * the benefit. */ - if (bio->bi_opf & REQ_ATOMIC) { - error = -EIO; + if (bio->bi_opf & REQ_ATOMIC) goto err_handle; - } good_sectors = first_bad - dev_sector; if (good_sectors < max_sectors) @@ -1489,17 +1485,16 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, r10_bio->sectors = max_sectors; if (r10_bio->sectors < bio_sectors(bio)) { - struct bio *split = bio_split(bio, r10_bio->sectors, - GFP_NOIO, &conf->bio_split); - if (IS_ERR(split)) { - error = PTR_ERR(split); - goto err_handle; - } - bio_chain(split, bio); allow_barrier(conf); - submit_bio_noacct(bio); + bio = bio_submit_split(bio, r10_bio->sectors, &conf->bio_split); wait_barrier(conf, false); - bio = split; + + if (!bio) { + set_bit(R10BIO_Returned, &r10_bio->state); + goto err_handle; + } + + bio->bi_opf &= ~REQ_NOMERGE; r10_bio->master_bio = bio; } @@ -1531,8 +1526,6 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, } } - bio->bi_status = errno_to_blk_status(error); - set_bit(R10BIO_Uptodate, &r10_bio->state); raid_end_bio_io(r10_bio); } diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 3f16ad6904a9..cc167e708125 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -165,6 +165,7 @@ enum r10bio_state { * so that raid10d knows what to do with them. */ R10BIO_ReadError, + R10BIO_Returned, /* If a write for this request means we can clear some * known-bad-block records, we set this flag. */ -- 2.39.2