]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
md/raid1,raid10: fix bio accounting for split md cloned bios
authorAbd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
Fri, 1 May 2026 11:46:51 +0000 (13:46 +0200)
committerYu Kuai <yukuai@fygo.io>
Sun, 31 May 2026 11:09:18 +0000 (19:09 +0800)
Use md_cloned_bio() to control bio accounting instead of relying
on r1bio_existed in raid1 or the io_accounting flag in raid10.

The previous logic does not reliably reflect whether a bio is an
md cloned bio. When a failed bio is split and resubmitted via
bio_submit_split_bioset() on the error path, this can lead to either
double accounting for md cloned bios, or missing accounting for bios
returned from bio_submit_split_bioset()

Fix this by using md_cloned_bio() to detect md cloned bios and
skip accounting accordingly.

Fixes: bb2a9acefaf9 ("md/raid1: switch to use md_account_bio() for io accounting")
Fixes: 820455238366 ("md/raid10: switch to use md_account_bio() for io accounting")
Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
Reviewed-by: Xiao Ni <xiao@kernel.org>
Link: https://patch.msgid.link/20260501114652.590037-4-abd.masalkhi@gmail.com
Signed-off-by: Yu Kuai <yukuai@fygo.io>
drivers/md/raid1.c
drivers/md/raid10.c

index 22458df5069e9d77db6ef262bb6df7714a09f2cd..603aa09088f05a01ce719a85feea8efbf6010f74 100644 (file)
@@ -1418,7 +1418,7 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
        }
 
        r1_bio->read_disk = rdisk;
-       if (!r1bio_existed) {
+       if (likely(!md_cloned_bio(mddev, bio))) {
                md_account_bio(mddev, &bio);
                r1_bio->master_bio = bio;
        }
index b38a0ccd4661a30cc7a5ebd8a63122bc7a51cdcc..5bd7698e0a1b543f337bb5cf9ac5d8b0eeed01f3 100644 (file)
@@ -1146,7 +1146,7 @@ static bool regular_request_wait(struct mddev *mddev, struct r10conf *conf,
 }
 
 static void raid10_read_request(struct mddev *mddev, struct bio *bio,
-                               struct r10bio *r10_bio, bool io_accounting)
+                               struct r10bio *r10_bio)
 {
        struct r10conf *conf = mddev->private;
        struct bio *read_bio;
@@ -1226,7 +1226,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
        }
        slot = r10_bio->read_slot;
 
-       if (io_accounting) {
+       if (likely(!md_cloned_bio(mddev, bio))) {
                md_account_bio(mddev, &bio);
                r10_bio->master_bio = bio;
        }
@@ -1552,7 +1552,7 @@ static void __make_request(struct mddev *mddev, struct bio *bio, int sectors)
                        conf->geo.raid_disks);
 
        if (bio_data_dir(bio) == READ)
-               raid10_read_request(mddev, bio, r10_bio, true);
+               raid10_read_request(mddev, bio, r10_bio);
        else
                raid10_write_request(mddev, bio, r10_bio);
 }
@@ -2867,7 +2867,7 @@ static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
 
        rdev_dec_pending(rdev, mddev);
        r10_bio->state = 0;
-       raid10_read_request(mddev, r10_bio->master_bio, r10_bio, false);
+       raid10_read_request(mddev, r10_bio->master_bio, r10_bio);
        /*
         * allow_barrier after re-submit to ensure no sync io
         * can be issued while regular io pending.