UFS 4.1 HID(Host Initiated Defragmentation)功能详解
文档信息
| 项目 | 内容 |
|---|---|
| 主题 | UFS HID(主机发起的碎片整理) |
| 适用规格 | JEDEC JESD220G(UFS 4.1,2025-01 发布);配套 JESD223F(UFSHCI 4.1) |
| 引入版本 | UFS 4.1 新增的可选特性;UFS 4.0 / 3.1 及更早版本无此功能 |
| 实现位置 | UFS 设备(Device)内部固件行为;主机通过 Query Request 访问,不需要 UFSHCI 新增寄存器 |
| 参考实现 | Linux mainline drivers/ufs/core/ufs-sysfs.c(ufs_sysfs_hid_group);QEMU hw/ufs 的 HID 行为模型 |
| 面向读者 | 设备侧固件 / FTL 工程师、主机侧 UFS 驱动工程师、特性验证人员 |
证据等级标注
本文对每条结论标注来源等级,便于复核与区分「规格规定」与「工程推断」:
| 标记 | 含义 |
|---|---|
| 〔S〕 | 规格 / JEDEC 定义,或原厂对规格的正式表述 |
| 〔K〕 | Linux 内核实现(补丁与 sysfs ABI 文档)中可查证的行为 |
| 〔E〕 | QEMU 设备模型中的模拟行为(非规格原文,但反映主流实现约定) |
| 〔G〕 | 工程实践与推断,非规格强制,落地时需与具体器件 datasheet 核对 |
1. 定义与术语澄清
HID = Host Initiated Defragmentation,主机发起的碎片整理。
一句话概括:主机通过 Query Attribute 指示设备「先分析内部物理碎片程度」,再「在我指定的空闲窗口、按我给定的数据量做一次物理碎片整理」,并可轮询进度与状态。
UFS 生态里缩写高度重叠,先做隔离,避免与已有概念混淆:
| 缩写 | 全称 | 与本主题的关系 |
|---|---|---|
| HID | Host Initiated Defragmentation | 本文主题,UFS 4.1 设备级可选特性 |
| USB HID | Human Interface Device | 完全无关,仅同名 |
| HPB | Host Performance Booster | 无关但常被混淆:HPB 把 L2P 映射缓存到主机内存以降低读延迟 |
| FBO | File Based Optimization(JESD231) | 相关但不同:FBO 用文件级 LBA 提示优化读路径 |
| BKOPS | Background Operations | 设备自主后台操作;HID 正是把 GC 时机交由主机决定的机制 |
| Discard / TRIM | --- | 让 LBA 数据失效,与整理物理布局不是一回事 |
| WB | WriteBooster | SLC 写缓存,与 HID 在 SLC 池与后台带宽上存在资源竞争 |
2. 为什么需要 HID
2.1 碎片是怎么产生的
NAND 不能原地覆盖写,形成了这条固有条链:
- 数据修改 → 写入新的物理页(out-of-place update),旧页置为失效;
- 设备维护 L2P(逻辑地址到物理地址)映射表指向新页;
- 小粒度随机写、元数据穿插写入 → 同一份逻辑上连续的数据在物理上被切成多段;
- 空间回收靠 GC:把多个源块中的有效页搬到新块,同时擦除旧块。
第 3 步产生物理碎片 ,第 4 步产生写放大。两者互为因果:碎片越多,GC 搬运越多。
2.2 碎片带来的三个代价
| 代价 | 机理 | 用户可感知的表现 |
|---|---|---|
| GC 时机不可控 | 设备按剩余空间/失效页比例自行触发 GC,主机无法预知 | 前台 IO 与 GC 撞车,尾延迟(99.9th)出现尖峰 |
| 写放大上升 | 整理/GC 需要搬迁有效页,1 次主机写变成多次 NAND 写 | 同等写入量下 P/E 消耗更快,寿命下降 |
| 读效率下降 | L2P 局部性变差、映射表缓存命中率降低;物理不连续导致预读失效 | 随机读 IOPS 掉档、读功耗升高 |
2.3 传统手段的局限
| 手段 | 局限 |
|---|---|
bBackgroundOpsStatus 只有 4 档状态 |
只能观测,不能预约「什么时候做」 |
bBKOPS_EN |
只能整体禁止/允许后台操作,粒度粗;长期禁止会拖垮后续写性能 |
| 主机文件系统级碎片整理(f2fs GC、ext4 e4defrag) | 只处理逻辑 碎片(LBA 分配连续性),对设备内物理布局无能为力 |
| 厂商私有 defrag 命令 | 各家不统一,不可移植,通常无标准状态机与进度上报 |
2.4 HID 的设计意图
JEDEC 对 UFS 4.1 该特性的正式表述是:「通过主机发起的数据碎片整理优化读取流量的新机制,实现更有效的内存维护。这使得垃圾收集可以延迟执行,在关键时刻保持不间断的快速性能。」〔S〕
拆开看,HID 提供三件事:
- 可观测 ------设备把「内部碎片有多严重」量化成一个主机可读的数值(
dHIDAvailableSize),而不是让主机靠性能退化去猜; - 可触发------主机可以显式要求设备做整理,而不是等设备自己判断;
- 可限流 ------主机可以指定本次只整理多少数据(
dHIDSize),把一次性的长耗时操作切成可控的小块。
一句话:把「什么时候付出整理代价」的决策权,从设备固件移到主机策略层。 这是 HID 与 BKOPS 最本质的区别。
3. 协议层接口
3.1 能力发现
HID 支持位在 Device Descriptor 的 dExtendedUFSFeaturesSupport 字段:
| 项目 | 值 | 说明 |
|---|---|---|
| 字段 | dExtendedUFSFeaturesSupport |
4 字节,大端 |
| 偏移 | 0x4F |
规格表中的固定偏移 |
| 相关位 | bit13 | 1 = 支持 HID |
| Linux 宏 | UFS_DEV_HID_SUPPORT = BIT(13) |
读取方式 get_unaligned_be32(desc_buf + 0x4F) 〔K〕 |
同一 dword 里相邻的位(便于对照,bUFSFeaturesSupport 已被废弃,统一看这个字段):
| bit | 特性 |
|---|---|
| 7 | HPB |
| 8 | WriteBooster |
| 12 | Device Level Exception |
| 13 | HID |
使用前提:wSpecVersion >= 4.1 且 bit13 = 1。老器件该字段为 0,写入 HID 属性会返回「无效 IDN / 无效参数」类错误。〔G〕
3.2 五个 Query Attribute(速查表)
| IDN | 规格名 | 方向 | 取值 | 语义 |
|---|---|---|---|---|
0x35 |
bDefragOperation |
写(可读) | 0 / 1 / 2 | HID 总开关与阶段触发:0 = 分析与整理全禁用;1 = 只允许分析;2 = 允许分析 + 整理 |
0x36 |
dHIDAvailableSize |
只读 | 4KB 为单位 | 分析阶段产出的「待整理碎片总量」 |
0x37 |
dHIDSize |
读 / 写 | 4KB 为单位 | 主机本次请求整理的数据量 |
0x38 |
bHIDProgressRatio |
只读 | 0~100(百分数) | 已整理量 / 请求量,进度百分比 |
0x39 |
bHIDState |
只读 | 0~5 | 当前 HID 状态 |
几个必须注意的细节:
- 宽度统一 :Query Attribute 事务固定携带 4 字节值(大端),即使字段名带
b前缀,传输宽度仍是 dword。 - 单位 :
0x36/0x37以 4KB 为单位(QEMU 模型的注释明确写 "fragmented 4KB units" / "host-requested defrag target (4KB units)")〔E〕。落地时应与器件 datasheet 核对,但按 4KB 处理与主流实现一致〔G〕。 - 进度下界不一致 :Linux sysfs 文档写
1 ~ 100〔K〕,QEMU 模型写0 ~ 100〔E〕。工程上建议用progress >= 100判定完成,不要依赖 0 的具体语义。 - 取值上限 :
dHIDSize是 32bit,按 4KB 单位理论可表达 16TB,实际受设备内部策略限制,写入过大会被截断为min(dHIDSize, dHIDAvailableSize)〔E〕。
3.3 访问路径与 UPIU
HID 属性全部走 Query 通道,不涉及新的 UPIU 类型,也不涉及 UFSHCI 寄存器扩展:
| 环节 | 内容 |
|---|---|
| 请求 | Query Request UPIU(Transaction Type 16h),Query Function = Read Attribute / Write Attribute |
| 定位域 | UPIU byte6 = IDN(0x35~0x39);byte7 = Index(HID 用 0);byte8 = Selector(HID 用 0) |
| 数据域 | UPIU byte12~15 = 4 字节属性值(大端) |
| 响应 | Query Response UPIU(Transaction Type 36h),Query Response Code:00h 成功,其它为各类失败码 |
| 并发 | 与读写命令共用 UTP 队列;Busy 时返回 FFh,主机需重试〔G〕 |
因为走 Query,每一次读进度/读状态本身都是总线事务,会唤醒设备、打断空闲状态------高频轮询反而破坏 HID 想要的「空闲窗口」,轮询间隔建议 1 秒级而非毫秒级〔G〕。
3.4 隐含的前置条件
| 条件 | 依据与说明 |
|---|---|
| 支持位 = 1 | 否则属性写入返回错误 〔S〕 |
| 设备处于 Active 电源模式 | Query 事务本身要求设备可响应 〔S〕 |
| 链路不应进入 Hibernate | Linux 参考实现在整个 HID 操作期间显式关闭 auto-hibernate(ufshcd_auto_hibern8_update(hba, 0)),完成后恢复 〔K〕。说明链路/设备休眠会中断 HID 推进 |
| 建议无前台 IO | QEMU 模型的状态机只在 ufs_process_idle() 中推进,即仅在设备空闲时前进 〔E〕 |
4. 状态机与执行流程
4.1 六个状态
| 值 | Linux 字符串 | 含义 | 主机应做什么 |
|---|---|---|---|
| 0 | idle |
空闲,尚未分析,或上次会话已收尾 | 需要开始时写 0x35 = 1(仅分析)或 = 2(分析 + 整理) |
| 1 | analysis_in_progress |
分析中(扫描映射/统计碎片) | 轮询 0x39,不要下发大块 IO |
| 2 | defrag_required |
分析完成,碎片量达到需要整理的程度 | 读 0x36 得碎片量 → 写 0x37 设定本次整理量 → 写 0x35 = 2 |
| 3 | defrag_in_progress |
整理中(搬迁有效页) | 轮询 0x38 看进度,避免前台 IO 抢占 |
| 4 | defrag_completed |
本次整理完成 | 读终态即复位,再写 0x35 = 0 收尾 |
| 5 | defrag_not_required |
分析判定无需整理(碎片低于阈值) | 写 0x35 = 0 收尾 |
4.2 状态迁移
| 当前状态 | 触发动作 | 目标状态 |
|---|---|---|
| Idle (0) | 主机写 0x35 = 1 |
Analysis In Progress (1) |
| Analysis In Progress (1) | 设备分析完成,碎片 ≥ 阈值 | Defrag Required (2) |
| Analysis In Progress (1) | 设备分析完成,碎片 < 阈值 | Defrag Not Required (5) |
| Defrag Required (2) | 主机写 0x37 定容量,再写 0x35 = 2 |
Defrag In Progress (3) |
| Defrag In Progress (3) | 进度达到 100% | Defrag Completed (4) |
| 任意状态 | 主机写 0x35 = 0 |
Idle (0),本次会话作废 |
| 任意状态 | 掉电 / 链路复位 / 设备复位 | Idle (0),0x35 复位 0,不跨会话保留 |
4.3 一次完整会话的时序
| 步 | 主机动作 | 设备行为 | 观察点 |
|---|---|---|---|
| 1 | 读 0x39 |
返回 0 | 确认起始状态为 Idle |
| 2 | 写 0x35 = 1 |
进入分析,状态置 1 | state 变 analysis_in_progress |
| 3 | 轮询 0x39 |
分析完成后置 2 或 5 | 分析耗时与容量、碎片分布相关 |
| 4 | 若为 2:读 0x36 |
返回碎片总量(4KB 单位) | 例如 65536 → 256MB |
| 5 | 写 0x37 = N |
记录本次目标量 | 建议 N = min(可用量, 策略上限) |
| 6 | 写 0x35 = 2 |
进入整理,状态置 3 | state 变 defrag_in_progress |
| 7 | 周期读 0x38 |
逐步推进 1 → 100 | 建议 1 秒级间隔 |
| 8 | 读 0x39 |
返回 4(或 5) | 读终态后设备把会话收尾 |
| 9 | 写 0x35 = 0 |
清零,回 Idle | 保险动作,防止异常残留 |
4.4 三个容易踩的行为细节
- 终态读取会复位会话 :QEMU 模型里,读取终态
bHIDState、或读到bHIDProgressRatio = 100,都会把 HID 收尾并回到 Idle〔E〕。因此主机「读到 4/5 就写0x35 = 0」的写法是自洽的〔K〕。 bDefragOperation会自动清零 :到达终态后设备自动把0x35清 0〔E〕。主机不能假设它一直保持 2;下一轮必须重写。- 部分整理是合法的 :实际整理量 =
min(dHIDSize, dHIDAvailableSize)〔E〕。给一个小dHIDSize就是「只整理一部分」,这也是主机控制单次代价、把长任务切片的主要手段。
5. 主机侧使用方式
5.1 Linux sysfs 节点
这套节点只在设备 dExtendedUFSFeaturesSupport bit13 = 1 时才可见(is_visible 回调控制)〔K〕。
节点(相对 <ufs_dev>/hid/) |
权限 | 对应 IDN | 取值 |
|---|---|---|---|
analysis_trigger |
只写 | 0x35 |
enable / disable |
defrag_trigger |
只写 | 0x35 |
enable(写 2)/ disable |
fragmented_size |
只读 | 0x36 |
十进制(4KB 单位) |
defrag_size |
读写 | 0x37 |
十进制(4KB 单位) |
progress_ratio |
只读 | 0x38 |
1~100 |
state |
只读 | 0x39 |
见 4.1 的字符串表 |
路径形如 /sys/bus/platform/devices/*.ufs/hid/。
5.2 操作实录(可直接粘贴)
sh
HID=$(ls -d /sys/bus/platform/devices/*.ufs/hid 2>/dev/null | head -1)
echo "start: $(cat $HID/state)"
# 阶段一:只做分析
echo enable > $HID/analysis_trigger
while [ "$(cat $HID/state)" = "analysis_in_progress" ]; do sleep 1; done
echo "after analysis: $(cat $HID/state), fragmented=$(cat $HID/fragmented_size) x 4KB"
# 阶段二:限定 256MB(65536 x 4KB)做整理
echo 65536 > $HID/defrag_size
echo enable > $HID/defrag_trigger
while :; do
s=$(cat $HID/state); p=$(cat $HID/progress_ratio)
echo " state=$s progress=$p%"
case "$s" in defrag_completed|defrag_not_required) break;; esac
sleep 1
done
# 收尾
echo disable > $HID/analysis_trigger
5.3 参考实现的自动闭环逻辑
Linux 首版补丁(ufs-hid.c)用延迟工作队列做轮询,决策表非常简洁〔K〕:
| 读到的状态 | 写入 0x35 |
|---|---|
| Idle (0) | 1(只分析) |
| Defrag Required (2) | 2(分析 + 整理) |
| Defrag Completed (4) / Not Required (5) | 0(禁用并收尾) |
| Analysis In Progress (1) / Defrag In Progress (3) | 不写,等下一轮 |
同时全程持有 runtime PM、关闭 auto-hibernate、调度次数上限 300 次后放弃。补丁演进中最终版把这套自动策略撤掉了------HID 的执行策略交给用户空间,内核只暴露 6 个 sysfs 节点。这个取舍本身值得注意:HID 的价值在于「什么时候做」由系统策略决定,而不是由驱动硬编码。
5.4 触发策略建议
| 维度 | 建议 |
|---|---|
| 时机 | 充电 + 灭屏 + 系统空闲(与 Android 的 idle maintenance 窗口合并) |
| 电量 | 高于 30%,避免整理耗电引发关机保护 |
| 温度 | 低于 thermal throttling 阈值;整理是持续写入,很容易顶到温控 |
| 前台 IO | 做 IO 空闲判定;避开安装应用、拍照录像、游戏加载等重压场景 |
| 单次量 | 用 dHIDSize 限流(如 256MB ~ 1GB / 次),把长任务切片 |
| 频率 | 每 N 天一次,或 dHIDAvailableSize 超过阈值才做 |
| 轮询 | 1 秒级;过密会不停唤醒设备,破坏 HID 依赖的空闲窗口 |
6. 设备侧(固件 / FTL)实现要点
这一节从设备固件视角给出落地要点,均为工程实践范畴〔G〕,规格只约束对外可见的属性语义。
6.1 碎片如何量化(dHIDAvailableSize 的口径)
规格只要求「报告待整理的碎片总量」,口径由厂商定义。三种常见口径:
| 口径 | 定义 | 优点 | 风险 |
|---|---|---|---|
| 碎片单元计数 | 每个物理不连续点计 1 个 4KB 单元 | 直观,与「按量整理」天然对齐 | 大文件少量碎片时数值偏小 |
| 非顺序有效页字节数 | 统计写入顺序被打乱的 valid page 总量 | 贴近真实读性能损失 | 统计开销大,需全量扫描 |
| run 长度分布 | 统计 L2P 中连续 run 长度 < 阈值 的 valid run 总量 | 与映射表局部性、预读命中直接相关 | 实现最复杂 |
选择原则:口径必须能支撑「按量整理」 。主机给的是 dHIDSize,设备要能据此挑出匹配规模的候选集合,否则进度无法对账。
6.2 分析阶段(Analysis)
- 纯读扫描:遍历 L2P / 块有效位图,不写 NAND,只消耗 CPU、SRAM 与时间。
- 必须可中断:前台命令到来时要能暂停,且不得持有长锁;建议以「映射表分段」为粒度设置检查点。
- 增量优先:256GB、4KB 映射粒度对应 6400 万条 L2P,全表扫描耗时不可忽视;建议只扫上电后被写脏的区域。
- 掉电即作废:分析结果不跨上电保留,上电后回 Idle。
- 时间可控 :主机在轮询
analysis_in_progress期间无法做别的 HID 动作,分析时长直接影响策略可行性,应设上限并在超时后强制降级为「放弃本次」。
6.3 整理阶段(Defrag)
基本动作与 GC 完全一致:读有效页 → 写新块 → 更新 L2P → 失效旧页 → 回收旧块。差异在调度权的归属。
| 设计点 | 建议 |
|---|---|
| 复用通路 | 与 GC 共用同一套 copy 引擎,避免两套搬迁逻辑产生一致性风险 |
| 目的块 | 优先从空白块池取,避免整理自身触发新一轮 GC |
| 选源策略 | 碎片度优先(有效页多且被打散)收益最大;可与「老化优先」加权,兼顾寿命 |
| 回填策略 | 按 LBA 顺序把碎片数据聚到新块,直接改善顺序读与预读 |
| 抢占粒度 | 以页/块为单位设检查点;前台 IO 到时保存进度让路,恢复时从检查点继续 |
| 进度单调 | 恢复后进度不得回退,否则主机看到的百分比会抖动 |
6.4 进度与状态一致性
bHIDProgressRatio= 已完成量 / 请求量 × 100,向下取整;跳到 100 只能发生在真正完成时。- 单调不降(除非主机重写
0x37开启新一轮)。 - 状态与进度必须自洽 :不能出现
state = defrag_completed而progress < 100。主机侧常见写法是「先读状态再读进度」,两者矛盾会直接触发策略误判。
6.5 与 BKOPS / 自主 GC 的协同
| 场景 | 建议行为 |
|---|---|
HID 已启用(0x35 != 0) |
抑制自主 GC 的主动触发,避免与 HID 争抢同一批源块;但保留「空间不足」的紧急 GC 优先权 |
| 紧急 GC 与 HID 冲突 | 紧急 GC 打断 HID → 状态回 Idle、进度作废,防止把设备整理到无空间可用 |
| 前台/后台阈值 | HID 期间可临时放宽 bBackgroundOpsTermLat,避免设备因超时强行插入后台操作 |
6.6 与 HPB / WriteBooster 的协同
| 特性 | 交互点 | 建议 |
|---|---|---|
| HPB | HID 改的是 PBA,主机缓存的映射副本会指向旧物理位置 | 搬页后必须让对应 HPB entry 失效或更新;保证上电后可重建 |
| WriteBooster | 两者都吃 SLC 池与后台写带宽 | 在 WB buffer 已刷出、SLC 池充足时做 HID;避免整理把 WB 剩余容量挤掉 |
| FBO | FBO 依赖文件级提示做读优化,HID 改变物理布局 | 顺序一致:先 HID 整理,再让 FBO 生效,不要交叉进行 |
6.7 断电、复位与异常
整理采用「先写新页 → 后更新 L2P → 再回收旧块」的原子序,因此任意点掉电最多丢进度、不丢数据。
| 场景 | 预期行为 |
|---|---|
| 整理中掉电 | 上电后数据完整;bDefragOperation 复位 0,bHIDState 回 Idle,dHIDSize 不保留 |
LINK RESET / 设备复位(bDeviceInit) |
同上,会话不跨复位保留 |
| FFU 期间 | 应拒绝或忽略 HID,避免与固件更新抢资源 |
| 温度超限 | 降速或返回 Busy,不得报致命错误 |
6.8 寿命与热预算
- 整理等价于额外的 NAND 写。WAF 增量 ≈ 迁移的有效页总量 / 总主机写入量,频繁全盘整理会显著加速磨损。
- 设备侧应结合
bDeviceLifeTimeEstA/B与PreEOLInfo做保护:接近 EOL 时限流或拒绝,避免「整理把器件提前写坏」。 - 主机侧限流(
dHIDSize)+ 设备侧保护,两者缺一不可。
7. 与其它特性的对比
| 特性 | 作用层次 | 触发方 | 改变什么 | 主要收益 | 起始版本 |
|---|---|---|---|---|---|
| HID | 设备内部物理布局 | 主机(Query) | PBA 映射重构 | 消除 GC 延迟尖峰、恢复读性能 | 4.1 |
| BKOPS | 设备内部物理布局 | 设备自主 | 同上 | 维持空闲态性能与寿命 | 2.0 起 |
| HPB | 主机内存中的 L2P 副本 | 主机 | 主机侧映射缓存 | 降低读延迟 | 3.1 |
| FBO | 文件级提示 | 主机 | 设备读调度与数据放置 | 提升读吞吐 | 4.0(JESD231) |
| WriteBooster | SLC 写缓存 | 主机使能 | 写路径 | 提升写突发性能 | 3.1 |
| Discard | L2P 逻辑失效 | 主机 | 逻辑地址空间 | 提前释放物理空间 | 早期版本 |
| 厂商私有 defrag | 设备内部 | 主机私有命令 | 物理布局 | 同上 | 私有实现 |
关键区分:HPB 是「少读映射表」,FBO 是「按文件摆放」,HID 是「把碎片搬掉」,WriteBooster 是「先写到 SLC」。四者互不替代,可以叠加。
8. 收益与代价
| 收益 | 代价 |
|---|---|
| 关键窗口(启动、拍照、游戏加载)不再被 GC 打断 | 额外 NAND 写,消耗 P/E 寿命 |
| 随机读 IOPS 与映射表局部性恢复 | 分析 + 整理期间占用设备与总线 |
| 整理行为可预期、可观测、可计量 | 全盘整理耗时可能达数分钟到数十分钟 |
| 可按量切片,具备工程可控性 | 与 WB / 热控争抢资源,实现复杂度高 |
注:HID 不会提升顺序读写带宽,整理期间反而会占用带宽。它的价值全部体现在「延迟稳定性」与「随机读」上。
9. 常见误区
| 误区 | 实际情况 |
|---|---|
| 以为 HID 是 USB HID | 完全无关,仅为缩写撞名 |
| 以为等同于主机文件系统碎片整理 | HID 不改 LBA 分配,只改物理位置,对文件系统透明 |
| 以为等同 Discard / TRIM | Discard 是让逻辑数据失效,HID 是搬运有效数据 |
| 以为能提升顺序带宽 | 不能,顺序性能还可能因整理期间带宽占用而短暂下降 |
跨厂商对比 dHIDAvailableSize |
口径由厂商定义,绝对值不可比,只能看同一器件的趋势 |
| 以为分析是瞬时完成的 | 分析需扫描映射结构,容量越大越慢 |
| 高频轮询进度 | 每次读都是 Query 事务,会唤醒设备、破坏空闲窗口 |
老内核看不到 hid/ 目录就以为器件不支持 |
先查 Device Descriptor 0x4F 的 bit13;内核版本不足时该 sysfs group 不存在 |
10. 验证清单
| 验证项 | 方法 | 判定标准 |
|---|---|---|
| 能力位 | 读 Device Descriptor offset 0x4F |
bit13 = 1 |
| 状态机闭环 | 按 5.2 手动走全流程 | 0 → 1 → 2 → 3 → 4 → 0(或 5) |
| 无碎片场景 | 全盘顺序写满再分析 | 直接进 defrag_not_required |
| 部分整理 | dHIDSize 设为远小于可用量 |
进度到 100%,但 fragmented_size 仍 > 0 |
| 数据一致性 | 整理前后全盘 hash 比对 | 完全一致 |
| 前台干扰 | 整理中用 fio 持续读写 | 数据正确、无 timeout / abort;进度暂停后可恢复 |
| 掉电 | 整理过程中随机断电 N 次 | 上电数据完整;状态回 Idle;无残留会话 |
| 寿命影响 | 统计整理前后 War 计数与 lifetime est | 增量与实际迁移量匹配 |
| 热保护 | 高温箱内触发整理 | 设备降速或返回 Busy,不报 fatal |
| 复位 | 整理中发 LINK RESET / 设备复位 | 会话作废,属性复位,数据完整 |
11. 参考资料
| 类别 | 内容 |
|---|---|
| 规格 | JEDEC JESD220G(UFS 4.1)、JESD223F(UFSHCI 4.1)、JESD231(FBO) |
| JEDEC 公告 | UFS 4.1 特性列表:Host-Initiated Defragmentation 为首项新增特性 |
| Linux 内核 | drivers/ufs/core/ufs-sysfs.c 中的 ufs_sysfs_hid_group;Documentation/ABI/testing/sysfs-driver-ufs 的 hid/* 节点说明 |
| 补丁演进 | HID support v1 ~ v6(2025-04 起,作者 Huan Tang / Wenxing Cheng,策略从内核自动改为用户空间控制) |
| 行为模型 | QEMU hw/ufs 的 Host Initiated Defragmentation 支持(IDN 0x35~0x39,4KB 单位,终态读复位) |
| 原厂表述 | KIOXIA UFS 4.1 新闻稿:「主机发起的碎片整理使垃圾收集可延迟执行,在关键时刻保持不间断的快速性能」 |
附录:一句话速记
- HID = 主机决定何时 GC,并按量限流。
- 五个属性:
0x35触发、0x36有多少碎片、0x37这次整多少、0x38进度、0x39状态。 - 状态:
Idle → 分析中 → 该整 / 不用整 → 整理中 → 完成。 - 值全是 4 字节 Query Attribute,单位 4KB,进度百分比 100 即完成。