YAFFS2 的 yaffs_ext_tags
数据结构详解
yaffs_ext_tags
是 YAFFS2 文件系统中用于 管理 NAND 闪存页的元数据 的核心结构体,存储在 NAND 的 OOB(Out-Of-Band)区域。它记录了数据块的归属、状态、校验信息等关键元数据,是 YAFFS2 实现 快速挂载、数据恢复 和 垃圾回收 的基础。以下是其详细解析:
1. 结构体定义
struct yaffs_ext_tags {
unsigned chunk_used:1; // 标记该页是否被使用(1=有效数据,0=空闲)
unsigned obj_id:20; // 所属对象的唯一标识符(文件/目录的ID)
unsigned chunk_id:10; // 页在文件中的逻辑编号(从0开始)
unsigned serial_number:15; // 序列号(用于块版本控制)
unsigned n_bytes:10; // 页内有效数据字节数(非全页写入时使用)
unsigned ecc:12; // ECC校验码(可选,依赖硬件支持)
unsigned block_bad:1; // 标记所属块是否为坏块(1=坏块)
// ... 其他扩展字段(根据YAFFS2版本可能不同)
};
2. 关键字段解析
字段 | 作用 |
---|---|
chunk_used |
标识当前页是否存储有效数据。若为 0 ,垃圾回收时可擦除该页。 |
obj_id |
关联到 yaffs_obj 的 obj_id ,表示该页属于哪个文件/目录。 |
chunk_id |
页在文件中的逻辑偏移量(如 0 表示文件头,1 表示第二个数据块)。 |
serial_number |
块的序列号,用于磨损均衡和版本控制(防止旧数据覆盖新数据)。 |
n_bytes |
实际存储的有效数据长度(支持非整页写入,如文件末尾部分填充)。 |
ecc |
错误校正码(ECC),用于检测和纠正数据错误(需硬件支持)。 |
block_bad |
标记当前页所属的块是否为坏块。若为 1 ,YAFFS2 会跳过该块。 |
3. 存储位置与布局
- OOB 区域:
每个 NAND 页的 OOB 区域通常为 64 字节,yaffs_ext_tags
占用其中一部分(具体大小由YAFFS2配置决定)。
典型布局:字段 字节偏移 长度(字节) chunk_used
0 1 (bit) obj_id
0-3 4 chunk_id
4-5 2 serial_number
6-7 2 n_bytes
8-9 2 ecc
10-13 4 block_bad
14 1 (bit)
4. 核心功能
(1) 数据归属与快速挂载
- 挂载时扫描:
YAFFS2 通过遍历所有块的yaffs_ext_tags
,快速重建文件系统元数据(如yaffs_obj
树)。 - 对象关联:
obj_id
和chunk_id
共同定位数据所属文件及位置,无需依赖中央目录表。
(2) 数据完整性保护
- ECC校验:
若硬件支持,YAFFS2 使用ecc
字段检测和纠正数据错误。 - 坏块隔离:
block_bad
标记坏块,防止后续写入操作使用已损坏的块。
(3) 垃圾回收(GC)优化
- 无效数据识别:
通过chunk_used
和obj_id
,GC 可快速识别可回收的无效页。 - 磨损均衡:
serial_number
记录块的擦除次数,优先回收低序列号的块。
5. 操作流程示例
(1) 写入数据页
struct yaffs_ext_tags tags;
memset(&tags, 0, sizeof(tags));
tags.chunk_used = 1;
tags.obj_id = file->obj_id;
tags.chunk_id = chunk_num;
tags.n_bytes = data_len;
tags.serial_number = block->seq_number