Skip to content

Commit 078d1d8

Browse files
Gregory Pricehailan94
authored andcommitted
md/raid0: use kvzalloc/kvfree for strip_zone and devlist allocations
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: syzbot+924649752adf0d3ac9dd@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/69adaba8.a00a0220.b130.0005.GAE@google.com/ Signed-off-by: Gregory Price <gourry@gourry.net> Reviewed-by: Yu Kuai <yukuai@fnnas.com> Reviewed-by: Li Nan <linan122@huawei.com> Link: https://lore.kernel.org/linux-raid/20260308234202.3118119-1-gourry@gourry.net/ Signed-off-by: Yu Kuai <yukuai@fnnas.com>
1 parent 2aa7227 commit 078d1d8

1 file changed

Lines changed: 9 additions & 9 deletions

File tree

drivers/md/raid0.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,13 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
143143
}
144144

145145
err = -ENOMEM;
146-
conf->strip_zone = kzalloc_objs(struct strip_zone, conf->nr_strip_zones);
146+
conf->strip_zone = kvzalloc_objs(struct strip_zone, conf->nr_strip_zones);
147147
if (!conf->strip_zone)
148148
goto abort;
149-
conf->devlist = kzalloc(array3_size(sizeof(struct md_rdev *),
150-
conf->nr_strip_zones,
151-
mddev->raid_disks),
152-
GFP_KERNEL);
149+
conf->devlist = kvzalloc(array3_size(sizeof(struct md_rdev *),
150+
conf->nr_strip_zones,
151+
mddev->raid_disks),
152+
GFP_KERNEL);
153153
if (!conf->devlist)
154154
goto abort;
155155

@@ -291,8 +291,8 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
291291

292292
return 0;
293293
abort:
294-
kfree(conf->strip_zone);
295-
kfree(conf->devlist);
294+
kvfree(conf->strip_zone);
295+
kvfree(conf->devlist);
296296
kfree(conf);
297297
*private_conf = ERR_PTR(err);
298298
return err;
@@ -373,8 +373,8 @@ static void raid0_free(struct mddev *mddev, void *priv)
373373
{
374374
struct r0conf *conf = priv;
375375

376-
kfree(conf->strip_zone);
377-
kfree(conf->devlist);
376+
kvfree(conf->strip_zone);
377+
kvfree(conf->devlist);
378378
kfree(conf);
379379
}
380380

0 commit comments

Comments
 (0)