The patch below does not apply to the 6.12-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y git checkout FETCH_HEAD git cherry-pick -x 22f166218f7313e8fe2d19213b5f4b3265f8c39e # <resolve conflicts, build, test, etc.> git commit -s git send-email --to 'stable@vger.kernel.org' --in-reply-to '2025101606-eggshell-static-9bca@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 22f166218f7313e8fe2d19213b5f4b3265f8c39e Mon Sep 17 00:00:00 2001 From: Yu Kuai yukuai3@huawei.com Date: Wed, 10 Sep 2025 14:30:44 +0800 Subject: [PATCH] md: fix mssing blktrace bio split events
If bio is split by internal handling like chunksize or badblocks, the corresponding trace_block_split() is missing, resulting in blktrace inability to catch BIO split events and making it harder to analyze the BIO sequence.
Cc: stable@vger.kernel.org Fixes: 4b1faf931650 ("block: Kill bio_pair_split()") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk
diff --git a/drivers/md/md-linear.c b/drivers/md/md-linear.c index 5d9b08115375..59d7963c7843 100644 --- a/drivers/md/md-linear.c +++ b/drivers/md/md-linear.c @@ -266,6 +266,7 @@ static bool linear_make_request(struct mddev *mddev, struct bio *bio) }
bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f1d8811a542a..1ba7d0c090f7 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -472,7 +472,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; end = zone->zone_end; @@ -620,7 +622,9 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) bio_endio(bio); return true; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); raid0_map_submit_bio(mddev, bio); bio = split; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f096f4d0fca7..64a1e0b47e87 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1384,7 +1384,9 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; r1_bio->master_bio = bio; @@ -1616,7 +1618,9 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; r1_bio->master_bio = bio; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 312e8a0e93e7..3d7b24d6b4eb 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1209,7 +1209,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); submit_bio_noacct(bio); wait_barrier(conf, false); @@ -1495,7 +1497,9 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); submit_bio_noacct(bio); wait_barrier(conf, false); @@ -1679,7 +1683,9 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return 0; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); /* Resend the fist split part */ submit_bio_noacct(split); @@ -1694,7 +1700,9 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return 0; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); /* Resend the second split part */ submit_bio_noacct(bio); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5112658ef5f6..96a6d63b3d62 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5493,8 +5493,10 @@ static struct bio *chunk_aligned_read(struct mddev *mddev, struct bio *raid_bio)
if (sectors < bio_sectors(raid_bio)) { struct r5conf *conf = mddev->private; + split = bio_split(raid_bio, sectors, GFP_NOIO, &conf->bio_split); bio_chain(split, raid_bio); + trace_block_split(split, raid_bio->bi_iter.bi_sector); submit_bio_noacct(raid_bio); raid_bio = split; }
From: John Garry john.g.garry@oracle.com
[ Upstream commit 74538fdac3e85aae55eb4ed786478ed2384cb85d ]
Add proper bio_split() error handling. For any error, set bi_status, end the bio, and return.
Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: John Garry john.g.garry@oracle.com Link: https://lore.kernel.org/r/20241111112150.3756529-5-john.g.garry@oracle.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/raid0.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 31bea72bcb01a..67ec633d27e26 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -464,6 +464,12 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) struct bio *split = bio_split(bio, zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO, &mddev->bio_set); + + if (IS_ERR(split)) { + bio->bi_status = errno_to_blk_status(PTR_ERR(split)); + bio_endio(bio); + return; + } bio_chain(split, bio); submit_bio_noacct(bio); bio = split; @@ -606,6 +612,12 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) if (sectors < bio_sectors(bio)) { struct bio *split = bio_split(bio, sectors, GFP_NOIO, &mddev->bio_set); + + if (IS_ERR(split)) { + bio->bi_status = errno_to_blk_status(PTR_ERR(split)); + bio_endio(bio); + return true; + } bio_chain(split, bio); raid0_map_submit_bio(mddev, bio); bio = split;
From: John Garry john.g.garry@oracle.com
[ Upstream commit b1a7ad8b5c4fa28325ee7b369a2d545d3e16ccde ]
Add proper bio_split() error handling. For any error, call raid_end_bio_io() and return.
For the case of an in the write path, we need to undo the increment in the rdev pending count and NULLify the r1_bio->bios[] pointers.
For read path failure, we need to undo rdev pending count increment from the earlier read_balance() call.
Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: John Garry john.g.garry@oracle.com Link: https://lore.kernel.org/r/20241111112150.3756529-6-john.g.garry@oracle.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/raid1.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index faccf7344ef93..31081d9e94025 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1317,7 +1317,7 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, struct raid1_info *mirror; struct bio *read_bio; int max_sectors; - int rdisk; + int rdisk, error; bool r1bio_existed = !!r1_bio;
/* @@ -1378,6 +1378,11 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, 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); submit_bio_noacct(bio); bio = split; @@ -1404,6 +1409,13 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, read_bio->bi_private = r1_bio; mddev_trace_remap(mddev, read_bio, r1_bio->sector); submit_bio_noacct(read_bio); + return; + +err_handle: + atomic_dec(&mirror->rdev->nr_pending); + bio->bi_status = errno_to_blk_status(error); + set_bit(R1BIO_Uptodate, &r1_bio->state); + raid_end_bio_io(r1_bio); }
static void raid1_write_request(struct mddev *mddev, struct bio *bio, @@ -1411,7 +1423,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, { struct r1conf *conf = mddev->private; struct r1bio *r1_bio; - int i, disks; + int i, disks, k, error; unsigned long flags; struct md_rdev *blocked_rdev; int first_clone; @@ -1557,6 +1569,11 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, if (max_sectors < bio_sectors(bio)) { struct bio *split = bio_split(bio, max_sectors, GFP_NOIO, &conf->bio_split); + + if (IS_ERR(split)) { + error = PTR_ERR(split); + goto err_handle; + } bio_chain(split, bio); submit_bio_noacct(bio); bio = split; @@ -1640,6 +1657,18 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
/* In case raid1d snuck in to freeze_array */ wake_up_barrier(conf); + return; +err_handle: + for (k = 0; k < i; k++) { + if (r1_bio->bios[k]) { + rdev_dec_pending(conf->mirrors[k].rdev, mddev); + r1_bio->bios[k] = NULL; + } + } + + bio->bi_status = errno_to_blk_status(error); + set_bit(R1BIO_Uptodate, &r1_bio->state); + raid_end_bio_io(r1_bio); }
static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
From: John Garry john.g.garry@oracle.com
[ Upstream commit 4cf58d9529097328b669e3c8693ed21e3a041903 ]
Add proper bio_split() error handling. For any error, call raid_end_bio_io() and return. Except for discard, where we end the bio directly.
Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Hannes Reinecke hare@suse.de Signed-off-by: John Garry john.g.garry@oracle.com Link: https://lore.kernel.org/r/20241111112150.3756529-7-john.g.garry@oracle.com Signed-off-by: Jens Axboe axboe@kernel.dk Stable-dep-of: 22f166218f73 ("md: fix mssing blktrace bio split events") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/raid10.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 6579bbb6a39a5..d02bd096824c8 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1153,6 +1153,7 @@ 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,6 +1204,10 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, 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); @@ -1233,6 +1238,11 @@ 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); }
static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, @@ -1341,9 +1351,10 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, struct r10bio *r10_bio) { struct r10conf *conf = mddev->private; - int i; + int i, k; sector_t sectors; int max_sectors; + int error;
if ((mddev_is_clustered(mddev) && md_cluster_ops->area_resyncing(mddev, WRITE, @@ -1469,6 +1480,10 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, 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); @@ -1488,6 +1503,26 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, raid10_write_one_disk(mddev, r10_bio, bio, true, i); } one_write_done(r10_bio); + return; +err_handle: + for (k = 0; k < i; k++) { + int d = r10_bio->devs[k].devnum; + struct md_rdev *rdev = conf->mirrors[d].rdev; + struct md_rdev *rrdev = conf->mirrors[d].replacement; + + if (r10_bio->devs[k].bio) { + rdev_dec_pending(rdev, mddev); + r10_bio->devs[k].bio = NULL; + } + if (r10_bio->devs[k].repl_bio) { + rdev_dec_pending(rrdev, mddev); + r10_bio->devs[k].repl_bio = NULL; + } + } + + bio->bi_status = errno_to_blk_status(error); + set_bit(R10BIO_Uptodate, &r10_bio->state); + raid_end_bio_io(r10_bio); }
static void __make_request(struct mddev *mddev, struct bio *bio, int sectors) @@ -1629,6 +1664,11 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) if (remainder) { split_size = stripe_size - remainder; split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split); + if (IS_ERR(split)) { + bio->bi_status = errno_to_blk_status(PTR_ERR(split)); + bio_endio(bio); + return 0; + } bio_chain(split, bio); allow_barrier(conf); /* Resend the fist split part */ @@ -1639,6 +1679,11 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) if (remainder) { split_size = bio_sectors(bio) - remainder; split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split); + if (IS_ERR(split)) { + bio->bi_status = errno_to_blk_status(PTR_ERR(split)); + bio_endio(bio); + return 0; + } bio_chain(split, bio); allow_barrier(conf); /* Resend the second split part */
From: Yu Kuai yukuai3@huawei.com
[ Upstream commit 22f166218f7313e8fe2d19213b5f4b3265f8c39e ]
If bio is split by internal handling like chunksize or badblocks, the corresponding trace_block_split() is missing, resulting in blktrace inability to catch BIO split events and making it harder to analyze the BIO sequence.
Cc: stable@vger.kernel.org Fixes: 4b1faf931650 ("block: Kill bio_pair_split()") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/md-linear.c | 1 + drivers/md/raid0.c | 4 ++++ drivers/md/raid1.c | 4 ++++ drivers/md/raid10.c | 8 ++++++++ drivers/md/raid5.c | 2 ++ 5 files changed, 19 insertions(+)
diff --git a/drivers/md/md-linear.c b/drivers/md/md-linear.c index 369aed044b409..d733ebee624b7 100644 --- a/drivers/md/md-linear.c +++ b/drivers/md/md-linear.c @@ -267,6 +267,7 @@ static bool linear_make_request(struct mddev *mddev, struct bio *bio) }
bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 67ec633d27e26..db1ab214250f9 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -470,7 +470,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; end = zone->zone_end; @@ -618,7 +620,9 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) bio_endio(bio); return true; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); raid0_map_submit_bio(mddev, bio); bio = split; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 31081d9e94025..4c6b1bd6da9bb 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1383,7 +1383,9 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; r1_bio->master_bio = bio; @@ -1574,7 +1576,9 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); submit_bio_noacct(bio); bio = split; r1_bio->master_bio = bio; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d02bd096824c8..b0062ad9b1d95 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1208,7 +1208,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); submit_bio_noacct(bio); wait_barrier(conf, false); @@ -1484,7 +1486,9 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, error = PTR_ERR(split); goto err_handle; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); submit_bio_noacct(bio); wait_barrier(conf, false); @@ -1669,7 +1673,9 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return 0; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); /* Resend the fist split part */ submit_bio_noacct(split); @@ -1684,7 +1690,9 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) bio_endio(bio); return 0; } + bio_chain(split, bio); + trace_block_split(split, bio->bi_iter.bi_sector); allow_barrier(conf); /* Resend the second split part */ submit_bio_noacct(bio); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 39e7596e78c0b..4fae8ade24090 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5484,8 +5484,10 @@ static struct bio *chunk_aligned_read(struct mddev *mddev, struct bio *raid_bio)
if (sectors < bio_sectors(raid_bio)) { struct r5conf *conf = mddev->private; + split = bio_split(raid_bio, sectors, GFP_NOIO, &conf->bio_split); bio_chain(split, raid_bio); + trace_block_split(split, raid_bio->bi_iter.bi_sector); submit_bio_noacct(raid_bio); raid_bio = split; }
linux-stable-mirror@lists.linaro.org