]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dma: map_benchmark: turn dma_sg_map_param buf into a flexible array
authorRosen Penev <rosenp@gmail.com>
Wed, 3 Jun 2026 03:17:58 +0000 (20:17 -0700)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Wed, 3 Jun 2026 06:20:02 +0000 (08:20 +0200)
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 <rosenp@gmail.com>
Reviewed-by: Qinxin Xia <xiaqinxin@huawei.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20260603031758.290538-1-rosenp@gmail.com
kernel/dma/map_benchmark.c

index 29eeb5fdf199cbbd531b0df705aabbb991671ffa..fdc070f419f66fa56e5aa774d0eea37925dfc89b 100644 (file)
@@ -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(&params->sgt, params->npages, GFP_KERNEL))
-               goto free_buf;
+               goto free_params;
 
        for_each_sgtable_sg(&params->sgt, sg, i) {
                params->buf[i] = (void *)__get_free_page(GFP_KERNEL);
@@ -166,9 +166,7 @@ free_page:
                free_page((unsigned long)params->buf[i]);
 
        sg_free_table(&params->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(&params->sgt);
 
-       kfree(params->buf);
        kfree(params);
 }