The buf pointer was kmalloc_array()'d immediately after the parent struct allocation, with the count (granule, validated to 1..1024 by the ioctl) trivially available beforehand. Move buf to the struct tail as a flexible array member and fold the two allocations into a single kzalloc_flex(), dropping the kfree(params->buf) in both the prepare error path and unprepare.
Add __counted_by for extra runtime analysis. Assisted-by: Claude:Opus-4.7 Signed-off-by: Rosen Penev <[email protected]> --- kernel/dma/map_benchmark.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/kernel/dma/map_benchmark.c b/kernel/dma/map_benchmark.c index 29eeb5fdf199..a65da5c7710c 100644 --- a/kernel/dma/map_benchmark.c +++ b/kernel/dma/map_benchmark.c @@ -121,35 +121,35 @@ static struct map_benchmark_ops dma_single_map_benchmark_ops = { struct dma_sg_map_param { struct sg_table sgt; struct device *dev; - void **buf; u32 npages; u32 dma_dir; + void *buf[] __counted_by(npages); }; static void *dma_sg_map_benchmark_prepare(struct map_benchmark_data *map) { + struct dma_sg_map_param *params; struct scatterlist *sg; + u32 npages; int i; - struct dma_sg_map_param *params = kzalloc(sizeof(*params), GFP_KERNEL); - - if (!params) - return NULL; /* * Set the number of scatterlist entries based on the granule. * In SG mode, 'granule' represents the number of scatterlist entries. * Each scatterlist entry corresponds to a single page. */ - params->npages = map->bparam.granule; + npages = map->bparam.granule; + + params = kzalloc_flex(*params, buf, npages); + if (!params) + return NULL; + + params->npages = npages; params->dma_dir = map->bparam.dma_dir; params->dev = map->dev; - params->buf = kmalloc_array(params->npages, sizeof(*params->buf), - GFP_KERNEL); - if (!params->buf) - goto out; - if (sg_alloc_table(¶ms->sgt, params->npages, GFP_KERNEL)) - goto free_buf; + if (sg_alloc_table(¶ms->sgt, npages, GFP_KERNEL)) + goto free_params; for_each_sgtable_sg(¶ms->sgt, sg, i) { params->buf[i] = (void *)__get_free_page(GFP_KERNEL); @@ -166,9 +166,7 @@ static void *dma_sg_map_benchmark_prepare(struct map_benchmark_data *map) free_page((unsigned long)params->buf[i]); sg_free_table(¶ms->sgt); -free_buf: - kfree(params->buf); -out: +free_params: kfree(params); return NULL; } @@ -183,7 +181,6 @@ static void dma_sg_map_benchmark_unprepare(void *mparam) sg_free_table(¶ms->sgt); - kfree(params->buf); kfree(params); } -- 2.54.0

