[PATCH v5 10/29] md: skip bitmap accounting for empty write ranges
From: Yu Kuai
Date: Sun Aug 02 2026 - 15:55:39 EST
From: Yu Kuai <yukuai@xxxxxxx>
mkfs.ext4 can submit zero-sector flush/FUA bios. These bios are WRITE
bios for md_write_start() purposes, but they do not cover any data sector
and must not dirty bitmap bits.
md bitmap accounting currently passes such bios to bitmap start_write().
For llbitmap this reaches llbitmap_start_write() with sectors == 0,
which underflows the end chunk calculation.
Personality bitmap mapping can also turn a non-empty bio into an empty
bitmap range when the requested sectors are outside the active bitmap
geometry. Treat both cases as not started, so the completion path will not
call end_write() for an empty range.
Tested-by: Mykola Marzhan <mykola@xxxxxxxxxxx>
Signed-off-by: Yu Kuai <yukuai@xxxxxxx>
---
drivers/md/md.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 58fb5453a819..f88952371b9b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9399,6 +9399,8 @@ static void md_bitmap_start(struct mddev *mddev,
mddev->pers->bitmap_sector(mddev, &md_io_clone->offset,
&md_io_clone->sectors);
+ if (!md_io_clone->sectors)
+ return;
fn(mddev, md_io_clone->offset, md_io_clone->sectors);
}
@@ -9419,7 +9421,8 @@ static void md_end_clone_io(struct bio *bio)
struct mddev *mddev = md_io_clone->mddev;
struct completion *reshape_completion = bio->bi_private;
- if (bio_data_dir(orig_bio) == WRITE && md_bitmap_enabled(mddev, false))
+ if (bio_data_dir(orig_bio) == WRITE && md_io_clone->sectors &&
+ md_bitmap_enabled(mddev, false))
md_bitmap_end(mddev, md_io_clone);
if (bio->bi_status && !orig_bio->bi_status)
@@ -9446,12 +9449,14 @@ static void md_clone_bio(struct mddev *mddev, struct bio **bio)
md_io_clone = container_of(clone, struct md_io_clone, bio_clone);
md_io_clone->orig_bio = *bio;
md_io_clone->mddev = mddev;
+ md_io_clone->sectors = 0;
if (blk_queue_io_stat(bdev->bd_disk->queue))
md_io_clone->start_time = bio_start_io_acct(*bio);
else
md_io_clone->start_time = 0;
- if (bio_data_dir(*bio) == WRITE && md_bitmap_enabled(mddev, false)) {
+ if (bio_data_dir(*bio) == WRITE && bio_sectors(*bio) &&
+ md_bitmap_enabled(mddev, false)) {
md_io_clone->offset = (*bio)->bi_iter.bi_sector;
md_io_clone->sectors = bio_sectors(*bio);
md_io_clone->rw = op_stat_group(bio_op(*bio));
--
2.51.0