Qu Wenruo @ 2026-02-24 17:18 +1030: > 在 2026/2/24 17:06, Miquel Sabaté Solà 写道: >> Qu Wenruo @ 2026-02-24 15:07 +1030: >> >>> 在 2026/2/24 10:14, Miquel Sabaté Solà 写道: >>>> Commit 2932ba8d9c99 ("slab: Introduce kmalloc_obj() and family") >>>> introduced, among many others, the kzalloc_objs() helper, which has some >>>> benefits over kcalloc(). >>>> Cc: Kees Cook >>>> Signed-off-by: Miquel Sabaté Solà >>>> --- >>>> fs/btrfs/block-group.c | 2 +- >>>> fs/btrfs/raid56.c | 8 ++++---- >>>> fs/btrfs/tests/zoned-tests.c | 2 +- >>>> fs/btrfs/volumes.c | 6 ++---- >>>> fs/btrfs/zoned.c | 5 ++--- >>>> 5 files changed, 10 insertions(+), 13 deletions(-) >>>> diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c >>>> index 37bea850b3f0..8d85b4707690 100644 >>>> --- a/fs/btrfs/block-group.c >>>> +++ b/fs/btrfs/block-group.c >>>> @@ -2239,7 +2239,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, >>>> if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) >>>> io_stripe_size = btrfs_stripe_nr_to_offset(nr_data_stripes(map)); >>>> - buf = kcalloc(map->num_stripes, sizeof(u64), GFP_NOFS); >>>> + buf = kzalloc_objs(*buf, map->num_stripes, GFP_NOFS); >>> >>> Not sure if we should use *buf for the type. >>> >>> I still remember we had some bugs related to incorrect type usage. >> Considering the type of 'buf' and how kzalloc_objs() will resolve the >> first argument '*buf', it should really just be equivalent to what was >> written before. > > Good luck if you miss the '*' for a structure pointer, and compiler won't give > you any warning. > > I still remembered that Johannes exposed such bug for me. > Unfortunately I didn't have exact lore link for it. That's a good point. Fortunately for us, this is what I get if I remove the star with GCC 15.2: fs/btrfs/block-group.c:2242:13: error: assignment to 'u64 *' {aka 'long long unsigned int *'} from incompatible pointer type 'u64 **' {aka 'long long unsigned int **'} [-Wincompatible-pointer-types] 2242 | buf = kmalloc_objs(buf, map->num_stripes, GFP_NOFS); | Hence, it looks like these kinds of errors will be catched by the compiler with these new helpers. This doesn't mean that we are 100% safe from corner cases, but at least there are some guarantees. > >> >>> >>> Another thing is, we may not want to use the kzalloc version. >>> We don't want to waste CPU time just to zero out the content meanwhile we're >>> ensured to re-assign the contents. >>> >>> Thus kmalloc_objs() maybe better. >> Yes, having a second look at this function, it looks like kmalloc_objs() >> might just be enough. If you don't mind, I will add another commit in v2 >> translating kzalloc_objs() into kmalloc_objs() wherever I see we can do >> this from the ones I've touched. This way we can easily revert in case >> things go south :) >> >>> >>> Thanks, >>> Qu >> Thanks, >> Miquel >> >>> >>> >>>> if (!buf) { >>>> ret = -ENOMEM; >>>> goto out; >>>> diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c >>>> index 02105d68accb..1ebfed8f0a0a 100644 >>>> --- a/fs/btrfs/raid56.c >>>> +++ b/fs/btrfs/raid56.c >>>> @@ -2110,8 +2110,8 @@ static int recover_sectors(struct btrfs_raid_bio *rbio) >>>> * @unmap_array stores copy of pointers that does not get reordered >>>> * during reconstruction so that kunmap_local works. >>>> */ >>>> - pointers = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS); >>>> - unmap_array = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS); >>>> + pointers = kzalloc_objs(*pointers, rbio->real_stripes, GFP_NOFS); >>>> + unmap_array = kzalloc_objs(*unmap_array, rbio->real_stripes, GFP_NOFS); >>>> if (!pointers || !unmap_array) { >>>> ret = -ENOMEM; >>>> goto out; >>>> @@ -2844,8 +2844,8 @@ static int recover_scrub_rbio(struct btrfs_raid_bio *rbio) >>>> * @unmap_array stores copy of pointers that does not get reordered >>>> * during reconstruction so that kunmap_local works. >>>> */ >>>> - pointers = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS); >>>> - unmap_array = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS); >>>> + pointers = kzalloc_objs(*pointers, rbio->real_stripes, GFP_NOFS); >>>> + unmap_array = kzalloc_objs(*unmap_array, rbio->real_stripes, GFP_NOFS); >>>> if (!pointers || !unmap_array) { >>>> ret = -ENOMEM; >>>> goto out; >>>> diff --git a/fs/btrfs/tests/zoned-tests.c b/fs/btrfs/tests/zoned-tests.c >>>> index da21c7aea31a..2bc3b14baa41 100644 >>>> --- a/fs/btrfs/tests/zoned-tests.c >>>> +++ b/fs/btrfs/tests/zoned-tests.c >>>> @@ -58,7 +58,7 @@ static int test_load_zone_info(struct btrfs_fs_info *fs_info, >>>> return -ENOMEM; >>>> } >>>> - zone_info = kcalloc(test->num_stripes, sizeof(*zone_info), GFP_KERNEL); >>>> + zone_info = kzalloc_objs(*zone_info, test->num_stripes, GFP_KERNEL); >>>> if (!zone_info) { >>>> test_err("cannot allocate zone info"); >>>> return -ENOMEM; >>>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c >>>> index e15e138c515b..c0cf8f7c5a8e 100644 >>>> --- a/fs/btrfs/volumes.c >>>> +++ b/fs/btrfs/volumes.c >>>> @@ -5499,8 +5499,7 @@ static int calc_one_profile_avail(struct btrfs_fs_info *fs_info, >>>> goto out; >>>> } >>>> - devices_info = kcalloc(fs_devices->rw_devices, sizeof(*devices_info), >>>> - GFP_NOFS); >>>> + devices_info = kzalloc_objs(*devices_info, fs_devices->rw_devices, GFP_NOFS); >>>> if (!devices_info) { >>>> ret = -ENOMEM; >>>> goto out; >>>> @@ -6067,8 +6066,7 @@ struct btrfs_block_group *btrfs_create_chunk(struct btrfs_trans_handle *trans, >>>> ctl.space_info = space_info; >>>> init_alloc_chunk_ctl(fs_devices, &ctl); >>>> - devices_info = kcalloc(fs_devices->rw_devices, sizeof(*devices_info), >>>> - GFP_NOFS); >>>> + devices_info = kzalloc_objs(*devices_info, fs_devices->rw_devices, GFP_NOFS); >>>> if (!devices_info) >>>> return ERR_PTR(-ENOMEM); >>>> diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c >>>> index ab330ec957bc..851b0de7bed7 100644 >>>> --- a/fs/btrfs/zoned.c >>>> +++ b/fs/btrfs/zoned.c >>>> @@ -1697,8 +1697,7 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg, >>>> return -EINVAL; >>>> } >>>> - raid0_allocs = kcalloc(map->num_stripes / map->sub_stripes, >>>> sizeof(*raid0_allocs), >>>> - GFP_NOFS); >>>> + raid0_allocs = kzalloc_objs(*raid0_allocs, map->num_stripes / map->sub_stripes, GFP_NOFS); >>>> if (!raid0_allocs) >>>> return -ENOMEM; >>>> @@ -1916,7 +1915,7 @@ int btrfs_load_block_group_zone_info(struct >>>> btrfs_block_group *cache, bool new) >>>> cache->physical_map = map; >>>> - zone_info = kcalloc(map->num_stripes, sizeof(*zone_info), GFP_NOFS); >>>> + zone_info = kzalloc_objs(*zone_info, map->num_stripes, GFP_NOFS); >>>> if (!zone_info) { >>>> ret = -ENOMEM; >>>> goto out;