Re: [PATCH] md/raid0: use kvzalloc/kvfree for strip_zone and devlist allocations
Li Nan <[email protected]>
| Newsgroups | gmane.linux.raid,gmane.linux.kernel,gmane.linux.kernel.mm |
|---|---|
| Message-ID | <[email protected]> |
在 2026/3/9 7:42, Gregory Price 写道: > syzbot reported a WARNING at mm/page_alloc.c:__alloc_frozen_pages_noprof() > triggered by create_strip_zones() in the RAID0 driver. > > When raid_disks is large, the allocation size exceeds MAX_PAGE_ORDER (4MB > on x86), causing WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER). > > Convert the strip_zone and devlist allocations from kzalloc/kzalloc_objs to > kvzalloc/kvzalloc_objs, which first attempts a contiguous allocation with > __GFP_NOWARN and then falls back to vmalloc for large sizes. Convert the > corresponding kfree calls to kvfree. > > Both arrays are pure metadata lookup tables (arrays of pointers and zone > descriptors) accessed only via indexing, so they do not require physically > contiguous memory. > > Reported-by: [email protected] > Signed-off-by: Gregory Price <[email protected]> > --- > drivers/md/raid0.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > > diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c > index ef0045db409f..5e38a51e349a 100644 > --- a/drivers/md/raid0.c > +++ b/drivers/md/raid0.c > @@ -143,13 +143,13 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) > } > > err = -ENOMEM; > - conf->strip_zone = kzalloc_objs(struct strip_zone, conf->nr_strip_zones); > + conf->strip_zone = kvzalloc_objs(struct strip_zone, conf->nr_strip_zones); > if (!conf->strip_zone) > goto abort; > - conf->devlist = kzalloc(array3_size(sizeof(struct md_rdev *), > - conf->nr_strip_zones, > - mddev->raid_disks), > - GFP_KERNEL); > + conf->devlist = kvzalloc(array3_size(sizeof(struct md_rdev *), > + conf->nr_strip_zones, > + mddev->raid_disks), > + GFP_KERNEL); > if (!conf->devlist) > goto abort; > > @@ -291,8 +291,8 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) > > return 0; > abort: > - kfree(conf->strip_zone); > - kfree(conf->devlist); > + kvfree(conf->strip_zone); > + kvfree(conf->devlist); > kfree(conf); > *private_conf = ERR_PTR(err); > return err; > @@ -373,8 +373,8 @@ static void raid0_free(struct mddev *mddev, void *priv) > { > struct r0conf *conf = priv; > > - kfree(conf->strip_zone); > - kfree(conf->devlist); > + kvfree(conf->strip_zone); > + kvfree(conf->devlist); > kfree(conf); > } > LGTM Reviewed-by: Li Nan <[email protected]> -- Thanks, Nan