]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nvmet-rdma: use kvcalloc for commands and responses arrays
authorIsrael Rukshin <israelr@nvidia.com>
Mon, 24 Nov 2025 06:49:20 +0000 (08:49 +0200)
committerKeith Busch <kbusch@kernel.org>
Thu, 4 Dec 2025 22:46:16 +0000 (14:46 -0800)
Replace kcalloc with kvcalloc for allocation of the commands and
responses arrays. Each command structure is 272 bytes and each
response structure is 672 bytes. These arrays typically exceed a
single page, and grow much larger with high queue depths
(e.g., commands >2MB, responses >170KB)

kvcalloc automatically falls back to vmalloc for large or fragmented
allocations, improving reliability. In our case, this memory is not
aimed for DMA operations and could be safely allocated by kvcalloc.
Using virtually contiguous memory helps to avoid allocation failures
and out-of-memory conditions common with kcalloc on large pools.

Signed-off-by: Israel Rukshin <israelr@nvidia.com>
Reviewed-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/target/rdma.c

index 0485e25ab797c0c64099c03b9d3b665acfba308b..9c12b2361a6d7a14609a6c68bcf114ca882fdc78 100644 (file)
@@ -367,7 +367,7 @@ nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev,
        struct nvmet_rdma_cmd *cmds;
        int ret = -EINVAL, i;
 
-       cmds = kcalloc(nr_cmds, sizeof(struct nvmet_rdma_cmd), GFP_KERNEL);
+       cmds = kvcalloc(nr_cmds, sizeof(struct nvmet_rdma_cmd), GFP_KERNEL);
        if (!cmds)
                goto out;
 
@@ -382,7 +382,7 @@ nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev,
 out_free:
        while (--i >= 0)
                nvmet_rdma_free_cmd(ndev, cmds + i, admin);
-       kfree(cmds);
+       kvfree(cmds);
 out:
        return ERR_PTR(ret);
 }
@@ -394,7 +394,7 @@ static void nvmet_rdma_free_cmds(struct nvmet_rdma_device *ndev,
 
        for (i = 0; i < nr_cmds; i++)
                nvmet_rdma_free_cmd(ndev, cmds + i, admin);
-       kfree(cmds);
+       kvfree(cmds);
 }
 
 static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
@@ -455,7 +455,7 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
                        NUMA_NO_NODE, false, true))
                goto out;
 
-       queue->rsps = kcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp),
+       queue->rsps = kvcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp),
                        GFP_KERNEL);
        if (!queue->rsps)
                goto out_free_sbitmap;
@@ -473,7 +473,7 @@ nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
 out_free:
        while (--i >= 0)
                nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
-       kfree(queue->rsps);
+       kvfree(queue->rsps);
 out_free_sbitmap:
        sbitmap_free(&queue->rsp_tags);
 out:
@@ -487,7 +487,7 @@ static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue)
 
        for (i = 0; i < nr_rsps; i++)
                nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
-       kfree(queue->rsps);
+       kvfree(queue->rsps);
        sbitmap_free(&queue->rsp_tags);
 }