From 4ffe28ed0d7ce7f2f72372cb13152ad37a43ff21 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Thu, 15 Jan 2026 01:12:34 +0800 Subject: [PATCH] md/raid5: make sure max_sectors is not less than io_opt Otherwise, even if user issue IO by io_opt, such IO will be split by max_sectors before they are submitted to raid5. For consequence, full stripe IO is impossible. BTW, dm-raid5 is not affected and still have such problem. Link: https://lore.kernel.org/linux-raid/20260114171241.3043364-7-yukuai@fnnas.com Signed-off-by: Yu Kuai --- drivers/md/raid5.c | 38 ++++++++++++++++++++++++++++---------- drivers/md/raid5.h | 1 + 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2fa63bd2431aa..84626ad71ffb8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -777,14 +777,14 @@ struct stripe_request_ctx { /* last sector in the request */ sector_t last_sector; + /* the request had REQ_PREFLUSH, cleared after the first stripe_head */ + bool do_flush; + /* * bitmap to track stripe sectors that have been added to stripes * add one to account for unaligned requests */ - DECLARE_BITMAP(sectors_to_do, RAID5_MAX_REQ_STRIPES + 1); - - /* the request had REQ_PREFLUSH, cleared after the first stripe_head */ - bool do_flush; + unsigned long sectors_to_do[]; }; /* @@ -6127,7 +6127,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) bi->bi_next = NULL; ctx = mempool_alloc(conf->ctx_pool, GFP_NOIO); - memset(ctx, 0, sizeof(*ctx)); + memset(ctx, 0, conf->ctx_size); ctx->first_sector = logical_sector; ctx->last_sector = bio_end_sector(bi); /* @@ -7743,6 +7743,25 @@ static int only_parity(int raid_disk, int algo, int raid_disks, int max_degraded return 0; } +static int raid5_create_ctx_pool(struct r5conf *conf) +{ + struct stripe_request_ctx *ctx; + int size; + + if (mddev_is_dm(conf->mddev)) + size = BITS_TO_LONGS(RAID5_MAX_REQ_STRIPES); + else + size = BITS_TO_LONGS( + queue_max_hw_sectors(conf->mddev->gendisk->queue) >> + RAID5_STRIPE_SHIFT(conf)); + + conf->ctx_size = struct_size(ctx, sectors_to_do, size); + conf->ctx_pool = mempool_create_kmalloc_pool(NR_RAID_BIOS, + conf->ctx_size); + + return conf->ctx_pool ? 0 : -ENOMEM; +} + static int raid5_set_limits(struct mddev *mddev) { struct r5conf *conf = mddev->private; @@ -7799,6 +7818,8 @@ static int raid5_set_limits(struct mddev *mddev) * Limit the max sectors based on this. */ lim.max_hw_sectors = RAID5_MAX_REQ_STRIPES << RAID5_STRIPE_SHIFT(conf); + if ((lim.max_hw_sectors << 9) < lim.io_opt) + lim.max_hw_sectors = lim.io_opt >> 9; /* No restrictions on the number of segments in the request */ lim.max_segments = USHRT_MAX; @@ -8071,12 +8092,9 @@ static int raid5_run(struct mddev *mddev) goto abort; } - conf->ctx_pool = mempool_create_kmalloc_pool(NR_RAID_BIOS, - sizeof(struct stripe_request_ctx)); - if (!conf->ctx_pool) { - ret = -ENOMEM; + ret = raid5_create_ctx_pool(conf); + if (ret) goto abort; - } ret = log_init(conf, journal_dev, raid5_has_ppl(conf)); if (ret) diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 6e3f07119fa4a..ddfe65237888c 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -692,6 +692,7 @@ struct r5conf { struct r5pending_data *next_pending_data; mempool_t *ctx_pool; + int ctx_size; }; #if PAGE_SIZE == DEFAULT_STRIPE_SIZE -- 2.47.3