Nvme盘加载调速失败问题分析
更新时间: 2026/06/08
在Gitcode上查看源码

问题背景

  • 单板类型:NA
  • 软件版本:openUBMC 25.12。
  • 涉及功能:风扇调速。
  • 触发条件:Presence信号未正确上报或初始化失败(可能由硬件抖动、I2C延迟、配置错误等引起)。
  • 业务表现:Nvme热插拔遍历,每个槽位都能正常读取温度并调速;在Disk22槽位发现没有温感,定位后发现没有调速且没有识别到在位。

问题复现步骤

  1. 在 openUBMC 25.12 LTS SP1 环境下对 NVMe 盘进行热插拔遍历测试。
  2. 将 NVMe 盘从某槽位拔出,观察系统日志。
  3. 将同一 NVMe 盘重新插入相同槽位。
  4. 检查该槽位对应的风扇调速策略是否正常加载、温度是否可感知。

关键日志信息

  1. 查看app.log日志,确认报错如下:
text
storage ERROR: tasks.lua(92): task [update_policy_connector22] error: ./opt/bmc/libmc/  lualib/mc/orm/object.lua:515: attempt to index field '__mdb_obj' (a boolean value)

  1. 确认 connector_Policy_01010217 对象的 .Presence 属性值为 0,系统未检测到设备在位:

定位过程

  1. 从app.log中的报错日志入手,分析 tasks.lua 中 update_policy 任务函数逻辑:通过 orm.get_object(connector_id) 获取对象失败返回 false,但代码未做有效性检查,直接访问其 __mdb_obj 字段导致运行时错误。
  2. 排查 Presence = 0 的原因:设备在位信号未正确上报或初始化失败,可能由硬件抖动、I2C 延迟、配置错误等引起。
  3. 进一步分析发现更深层原因:NVMe 盘上次拔出时,名为 update_policy_connector[Slot] 的定时任务未被正确停止。物理对象(VPD Connect 对象)虽已卸载,但其关联任务仍在后台运行。
  4. 同槽位硬盘再次插入时,系统尝试创建同名新任务,框架的同名任务机制阻止创建新任务,导致过期旧任务持续运行,反复访问已失效的对象变量,日志持续报错。
  5. 定位到代码层面根因:任务使用 c_tasks.get_instance() 方式创建,不属于"发起创建的对象";c_vpd_connect 对象的析构函数 dtor() 中缺少停止任务的代码,导致拔出时任务成为"孤儿"未被清理。

问题原因

NVMe 盘拔出时,c_vpd_connect 对象的析构函数 dtor() 未停止关联的 update_policy_connector 定时任务,导致旧任务残留运行;重新插入同槽位硬盘后,框架的同名任务机制阻止创建新任务,旧任务持续访问已失效对象变量,调速策略无法正常加载。

解决方案

  1. 推荐方案:改用 self:new_task 方式创建任务。此方式创建的任务会自动与对象实例绑定,对象被卸载(析构)时框架自动停止所有属于该对象的任务,无需手动清理。
  2. 备选方案:在 c_vpd_connect 对象的析构函数 dtor() 中手动停止相关任务:
lua
function c_vpd_connect:dtor()
    local task_name = string.format('update_vpd_connector%s', self.Slot)
    local task = c_tasks.get_instance():get_task(task_name)
    if task then
        task:stop()
    end
end
  1. 辅助优化:在访问对象字段前增加类型校验,增强代码健壮性;优化 Scanner 防抖计数配置,避免硬件抖动导致 Presence 误判。