Repository navigation
[nvme] fix: memory leak per inactive namespace in nvme_scan_device() - #11920
usualtreee wants to merge 1 commit into
Conversation
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: RT-Thread#11919
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
📌 Code Review Assignment🏷️ Tag: componentsReviewers: @Maihuanyi Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2026-10-23 10:59 CST)
📝 Review Instructions
|
|
独立复跑完成,补丁有效。数据贴在下面,另外有一处数字需要你确认一下。 环境
三组数字(本机)
推导:
交叉验证:我自己按同样思路写了一份补丁(calloc 后移 + 注册失败释放),跑出来 used=5,859,200 / available=61,249,664,与本 PR 相差 56 字节(编译布局噪声),功能等价。所以我那份不提 PR 了。 需要你确认的一处你给的三组是:不带设备 66,965,536、修复前 65,795,936、修复后 66,948,536。 按这组数字推:
但我这边修复后的正常占用是 803,392 B,差了将近 47 倍。一个挂着 4 个 IO queue( 可能的原因:
能否确认一下修复后那次 diff 复核(按项目要求只看两处)
另外确认两点没有引入新问题:
一个小建议(不影响合入): |
拉取/合并请求描述:(PR description)
为什么提交这份PR (why to submit this PR)
修复 issue #11919:
nvme_scan_device()(components/drivers/nvme/nvme.c)在发出每个命名空间的 Identify 命令之前就分配了一个 4480 字节的struct rt_nvme_device,但设备上报的nn(Identify Controller 的命名空间数量字段,QEMU 报 nn=256 而实际只暴露 1 个命名空间)会让循环遍历所有 nsid,每个未激活命名空间都泄漏这份内存:if (!id->nsze) continue;(QEMU 下 255 次)rt_hw_blk_disk_register()失败时goto _free_res在 bsp/qemu-virt64-aarch64 上实测,挂载 QEMU NVMe 设备后可用堆内存比不挂载少约 1.17 MB(1,169,600 字节)。
你的解决方案是什么 (what is your solution)
rt_calloc移到if (!id->nsze) continue;之后——只在命名空间确认为激活后才分配;rt_hw_blk_disk_register()失败路径补rt_free(ndev),消除错误路径的泄漏。修改文件:
components/drivers/nvme/nvme.c(+9/-7)请提供验证的bsp和config (provide the config and bsp)
RT_USING_NVME+RT_NVME_PCI)-M virt,acpi=on,its=on,gic-version=2 -cpu max -m 128M -smp 4-device nvme,id=nvme-ctrl-0,serial=deadbeef -drive if=none,file=nvme.img,format=raw,id=nvme0 -device nvme-ns,drive=nvme0验证方法:同一份固件分别带/不带 NVMe 设备启动,msh 里执行
free对比 available size:修复前缺口 = 1,169,600 字节(≈1.1 MB),即 255 个未激活命名空间 × 每命名空间 ~4.5 KB;
修复后 available 回到基线附近,剩余 ~17 KB 为 1 个激活命名空间 + 控制器的正常占用,泄漏归零。
action: (本地 qemu 实测;CI 编译由仓库 workflow 执行)
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up