创建逻辑盘对象概率性超时



2026-01-09 02:25:44.204792 storage ERROR: app_preloader.lua(64): co[thread: 0x2aac1f0ca788] abnormal exit, err: kepler.class.ObjectDuplicateDefined: Class DiskArray’s object /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010A03/DiskArrays/5 duplicate defined.

日志打印显示task任务在初始状态后,10%之后,尝试创建DiskArray对象重复,然后应该是将整个线程崩掉了。但是TASK对象依然存在,也还在树上。


有两部分内容的疑问。

  1. Task对象意外崩掉后,有没有机制能够进行任务回收?目前看虽然task_mgmt在storage组件,但是上树或者其它动作应该都是在闭源里的;
  2. DiskArrays对象重复的原因是什么?添加逻辑盘时也不需要指定DiskArrayID,均由代码进行处理,这部分需要考虑加固一下。

答案内容由AI生成,仅供参考:

:white_check_mark: 解决方案建议

1. 修复对象重复注册问题

:white_check_mark: 方案一:注册前进行存在性检查

-- 伪代码示例
if not object_exists(path) then
    register_object(path, class_name)
else
    log:warning("Object already exists: %s", path)
    -- 可选择 reload 或 skip
end

:white_check_mark: 对标原则:参考“【persistence】问题定位方法&FAQ”中的建议 —— “用 select 来判断数据是否存在”。

:white_check_mark: 方案二:确保主键生成唯一性

  • 使用 UUID 或结合 Controller ID、Array ID 构造全局唯一路径。
  • 避免直接使用简单的整数索引作为唯一标识。

:white_check_mark: 方案三:优化 CSR 加载顺序

  • 分离 PCIeDeviceController 的加载流程,保证 DeviceName Slot 分配完成后,再初始化依赖它的 DiskArray

2. 实现任务异常回收机制

:white_check_mark: 建议机制设计

功能 实现方式
异常捕获 在任务执行主流程包裹 pcallxpcall,捕获异常并记录堆栈。
状态更新 异常时强制设置:
  • .State = "Exception"
  • .EndTime = now()
  • .Message = "ObjectDuplicateDefined" |
    | 自动清理 | 定期扫描长时间处于 Running 状态的任务,并结合线程存活状态判断是否“僵尸任务”,予以清理。 |
    | 事件上报 | 触发 TaskFailed 事件供上层告警系统订阅。 |

:light_bulb: 建议将此机制纳入 task_mgmt.lua 模块统一管理。


3. 加固 Create Logical Disk 流程

流程加固点:

步骤 加固建议
1. 接收参数 校验 ArrayId 是否有效,是否已加载
2. 获取 DiskArray 查询资源树 /DiskArray/<id> 是否存在,复用而非重建
3. 创建逻辑盘 调用 CreateLogicalDriveOnExistedArray 方法(已有支持)
4. 更新状态 成功后更新 .Progress 至 100,并设置 .State = "Completed"
点击此处查看详细分析解答

存储管理中创建逻辑盘对象概率性超时问题分析

根据提供的日志和系统信息,创建逻辑盘对象过程中出现概率性超时,其根本原因在于 DiskArray 对象重复注册导致任务线程异常退出。以下是对问题的详细分析与解答。


:magnifying_glass_tilted_left: 问题现象总结

  1. 用户在 Web 界面尝试创建逻辑盘(Logical Drive),系统显示“创建中”。
  2. 操作日志中记录了任务(Task)的启动和初始执行阶段:
    • 任务 ID:2773900889
    • 状态从 New 更新为 Running
    • 进度推进至 10%
  3. 随后关键错误日志出现:
    ERROR: app_preloader.lua(64): abnormal exit, err: kepler.class.ObjectDuplicateDefined: Class DiskArray's object /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010A03/DiskArrays/5 is already registered
    
  4. 任务线程崩溃,但 Task 对象仍存在于资源树中,状态未更新为失败或完成,造成“悬空任务”。

:pushpin: 核心问题分析

一、DiskArray 对象重复定义的原因

1. DiskArray 实体说明

  • 实体定义bmc.kepler.Systems.Storage.DiskArray 是一个管理 RAID 组配置和元数据的系统级对象。
  • 关键属性
    • Id:RAID 组唯一编号(由 RAID 卡读取)
    • RefVolumes:关联的逻辑盘列表
    • UsedSpaceMiB, TotalFreeSpaceMiB:空间使用情况

2. 问题触发机制

从日志可见:

Class DiskArray's object /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010A03/DiskArrays/5 is already registered

表明系统试图再次注册一个已存在的 DiskArray 实例,违反了对象唯一性原则。

可能原因包括:
原因 分析
持久化数据冲突 在系统启动或任务执行过程中,DiskArray 对象可能已被先前的流程加载进内存数据库。当创建新逻辑盘时再次尝试加载同一 DiskArray,导致主键冲突。这与搜索结果中提到的“ORM对象创建时主键值与已有数据冲突”一致。
多线程/异步加载竞争 update_drive_slot_info() 等定时任务与其他 RAID 初始化任务并发执行,可能导致对 DiskArray 的重复处理。
Controller 加载时序问题 如搜索结果 #3 所述,ControllerPCIeDevice 在同一 CSR 中同时处理,存在加载时序依赖风险。若 DiskArray 的初始化依赖未完成即被访问,可能触发重复注册尝试。
Cache/Session 脏数据残留 上次操作未完全清理资源树路径,导致新任务误判需重新创建对象。

二、任务线程崩溃后未被回收的问题

1. Task 生命周期管理现状

  • 任务创建:由 task_mgmt.lua 创建并上树,路径为:
    /bmc/kepler/Systems/1/Storage/Controllers/Controller_1_0101010A03/TaskService/Tasks/2773900889
    
  • 状态字段
    • .State: "Running"
    • .Progress: 10
    • .EndTime: ""(未结束)

2. 崩溃后无回收机制的表现

尽管线程异常退出(abnormal exit),但:

  • 任务对象仍然存在于资源树中;
  • 没有自动将 .State 更新为 ExceptionFailed
  • 没有触发 .EndTime 设置与事件上报。

:white_check_mark: 结论:当前系统缺乏对“任务执行线程崩溃”的异常捕获与善后处理机制。


:hammer_and_wrench: 问题根因归纳

项目 内容
直接原因 创建逻辑盘过程中尝试重复注册已存在的 DiskArray 对象,引发 ObjectDuplicateDefined 异常,导致协程异常退出。
根本原因 - 对象注册缺乏幂等控制(缺少“是否存在”检查)
- 对象生命周期管理与时序控制不足
- 异常任务无自动回收与状态更新机制
影响范围 所有涉及 DiskArray 访问的操作,如创建逻辑盘、刷新阵列信息等,均可能概率性失败。

:white_check_mark: 解决方案建议

1. 修复对象重复注册问题

:white_check_mark: 方案一:注册前进行存在性检查

-- 伪代码示例
if not object_exists(path) then
    register_object(path, class_name)
else
    log:warning("Object already exists: %s", path)
    -- 可选择 reload 或 skip
end

:white_check_mark: 对标原则:参考“【persistence】问题定位方法&FAQ”中的建议 —— “用 select 来判断数据是否存在”。

:white_check_mark: 方案二:确保主键生成唯一性

  • 使用 UUID 或结合 Controller ID、Array ID 构造全局唯一路径。
  • 避免直接使用简单的整数索引作为唯一标识。

:white_check_mark: 方案三:优化 CSR 加载顺序

  • 分离 PCIeDeviceController 的加载流程,保证 DeviceName Slot 分配完成后,再初始化依赖它的 DiskArray

2. 实现任务异常回收机制

:white_check_mark: 建议机制设计

功能 实现方式
异常捕获 在任务执行主流程包裹 pcallxpcall,捕获异常并记录堆栈。
状态更新 异常时强制设置:
  • .State = "Exception"
  • .EndTime = now()
  • .Message = "ObjectDuplicateDefined" |
    | 自动清理 | 定期扫描长时间处于 Running 状态的任务,并结合线程存活状态判断是否“僵尸任务”,予以清理。 |
    | 事件上报 | 触发 TaskFailed 事件供上层告警系统订阅。 |

:light_bulb: 建议将此机制纳入 task_mgmt.lua 模块统一管理。


3. 加固 Create Logical Disk 流程

流程加固点:

步骤 加固建议
1. 接收参数 校验 ArrayId 是否有效,是否已加载
2. 获取 DiskArray 查询资源树 /DiskArray/<id> 是否存在,复用而非重建
3. 创建逻辑盘 调用 CreateLogicalDriveOnExistedArray 方法(已有支持)
4. 更新状态 成功后更新 .Progress 至 100,并设置 .State = "Completed"

:puzzle_piece: 相关知识支持

:white_check_mark: 支持创建逻辑盘的方法

  • CreateVolumeInExistingArray
    在已有阵列上创建逻辑盘,支持参数如 ArrayId, Capacity, RaidType 等。
  • CreateLogicalDriveOnExistedArray
    底层命令,由 SML 层调用 RAID 控制器实现。

:white_check_mark: 关联对象模型结构

/bmc/kepler/Systems/1/
 └─ Storage/
    └─ Controllers/
       └─ Controller_1_0101010A03/
          ├─ DiskArray/0 → RAID组信息(Id, RefVolumes, 空间等)
          ├─ LogicalDrives/ → 逻辑盘列表
          └─ TaskService/
             └─ Tasks/2773900889 → 当前任务对象

:memo: 总结与建议

问题 建议措施
DiskArray 重复注册 增加存在性判断逻辑,避免重复加载;优化 CSR 解析时序
任务崩溃后悬空 增强异常捕获机制,实现状态回写与自动回收
概率性超时 引入幂等性控制、资源预检、并发锁机制,提升稳定性

:end_arrow: 最终目标:构建健壮、可追溯、可恢复的存储管理任务体系,避免因底层对象冲突导致用户操作失败且无法感知。


文档参考来源:

  • bmc.kepler.Systems.Storage.DiskArray 实体描述
  • CreateLogicalDriveOnExistedArray 方法定义
  • 搜索结果中关于持久化冲突、主键冲突、任务管理等问题分析

相关链接:

  1. 【问题求助】【storage】背板csr中硬盘槽位配置进行调整后,web界面概率出现卡对象重复出现
  2. 【storage】【问题求助】双raid卡时概率 性有一张raid 卡 数据信息无法刷新成功
  3. 偶现raid卡 9560-8i通信异常触发告警,一段时间后又消除告警
  4. 后置背板上的两个硬盘组raid失败
  5. 上下电常见问题指南 | 文档中心 | openUBMC

1.需要在可能存在抛错的流程中pcall,防止意外退出,没有正确更新Task的状态与进度。
这个框架提供的create_task方法第四个参数为timeout,当前没有传递,可以考虑加固传递个超时参数,这样这个任务在超时后会结束。
上面的两种方法都是加固任务不结束的问题。
2.逻辑盘ID 阵列ID全是带内传过来的,不是BMC这边分配的,这个问题疑似时序问题,待加日志定位,这个问题的需要进一步定位解决

修复创建RAID逻辑盘概率性卡住-storage-AtomGit | GitCode
该问题在LTS分支已有该PR修复,main分支可参考修复,问题原因为:例测更新array_list的任务和创建逻辑盘触发的更新array_list的任务概率性撞上,导致冲突.