From 0581b812bd405135f4b91f50f3e490f132ebff4c Mon Sep 17 00:00:00 2001 From: usualtreee <1340399194@qq.com> Date: Fri, 23 Oct 2026 10:39:47 +0800 Subject: [PATCH] [nvme] fix: memory leak per inactive namespace in nvme_scan_device() nvme_scan_device() allocates a 4480-byte struct rt_nvme_device before issuing the per-namespace Identify command. The device-controlled nn field from Identify Controller (QEMU reports nn=256 while exposing a single namespace) makes the loop run over every nsid, and for every inactive namespace the allocation is leaked: - on the !id->nsze path (the main path, 255 times with QEMU), and - on the rt_hw_blk_disk_register() error path. Reproduced on bsp/qemu-virt64-aarch64: with a QEMU NVMe device attached, total used free shared buff/cache available Mem: 8002344 689772 6463032 4172 1038688 7312572 Swap: 2097152 0 2097152 reports ~1.17 MB (1,169,600 bytes) less available heap than without it. Allocate the device only after the namespace is confirmed active (id->nsze != 0), and free it when the block disk registration fails. Refs: #11919 --- components/drivers/nvme/nvme.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/components/drivers/nvme/nvme.c b/components/drivers/nvme/nvme.c index 260e1fb0469a..176ab9246afc 100644 --- a/components/drivers/nvme/nvme.c +++ b/components/drivers/nvme/nvme.c @@ -1072,13 +1072,7 @@ static rt_err_t nvme_scan_device(struct rt_nvme_controller *nvme, /* NVME Namespace is start with "1" */ for (rt_uint32_t nsid = 1; nsid <= number_of_ns; ++nsid) { - struct rt_nvme_device *ndev = rt_calloc(1, sizeof(*ndev)); - - if (!ndev) - { - err = -RT_ENOMEM; - goto _free_res; - } + struct rt_nvme_device *ndev; rt_memset(id, 0, sizeof(*id)); if ((err = nvme_identify(nvme, nsid, 0, id))) @@ -1091,6 +1085,13 @@ static rt_err_t nvme_scan_device(struct rt_nvme_controller *nvme, continue; } + ndev = rt_calloc(1, sizeof(*ndev)); + if (!ndev) + { + err = -RT_ENOMEM; + goto _free_res; + } + ndev->ctrl = nvme; rt_memcpy(&ndev->id, id, sizeof(ndev->id)); @@ -1108,6 +1109,7 @@ static rt_err_t nvme_scan_device(struct rt_nvme_controller *nvme, if ((err = rt_hw_blk_disk_register(&ndev->parent))) { + rt_free(ndev); goto _free_res; }