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 1/2] [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; } From 95aee78097870c2fd9f8f03cddb6f7e371a46aa1 Mon Sep 17 00:00:00 2001 From: usualtreee <1340399194@qq.com> Date: Mon, 26 Oct 2026 10:31:10 +0800 Subject: [PATCH 2/2] nvme: clear ndev after freeing it on register failure path Set ndev to RT_NULL right after rt_free() in the block device register failure path, so a future edit cannot dereference a stale pointer. No behaviour change. --- components/drivers/nvme/nvme.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/drivers/nvme/nvme.c b/components/drivers/nvme/nvme.c index 176ab9246afc..12e4a3b551a3 100644 --- a/components/drivers/nvme/nvme.c +++ b/components/drivers/nvme/nvme.c @@ -1110,6 +1110,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); + ndev = RT_NULL; goto _free_res; }