update
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
# repo22 架构设计
|
||||
|
||||
## 设计目标
|
||||
|
||||
repo22 提供尽量贴近 Linux `fs/erofs` 职责划分的 FreeBSD 15
|
||||
只读实现,同时对 FreeBSD vnode、GEOM、pager、`dev_t` 和 NFS FID 语义做
|
||||
必要适配。
|
||||
|
||||
## 核心原则
|
||||
|
||||
1. **Linux 对齐**:函数命名、文件组织、代码排序尽可能匹配 Linux 版本
|
||||
2. **最小抽象**:避免不必要的封装层
|
||||
3. **安全优先**:保留 repo19 的所有安全修复
|
||||
4. **可维护性**:便于社区维护和与上游同步
|
||||
|
||||
## 文件组织
|
||||
|
||||
```
|
||||
src/
|
||||
├── super.c - 超级块、挂载、VFS 集成
|
||||
├── inode.c - inode 读取和 vnode 管理
|
||||
├── data.c - 数据块映射和解压缩
|
||||
├── namei.c - 路径查找(二分搜索)
|
||||
├── dir.c - 目录遍历和输出
|
||||
├── xattr.c - 扩展属性和 ACL
|
||||
├── erofs_vnops.c - VFS vnode 操作实现
|
||||
├── decompressor.c - 压缩配置解析和统一调度
|
||||
├── decompressor_lz4.c - FreeBSD 有界 LZ4 后端
|
||||
├── decompressor_lzma.c - MicroLZMA 后端
|
||||
├── decompressor_deflate.c - DEFLATE 后端
|
||||
├── decompressor_zstd.c - 可选 ZSTDIO 后端
|
||||
├── zmap.c - 压缩逻辑块映射
|
||||
├── zdata.c - 压缩数据读取
|
||||
├── internal.h - 内存结构和内部 API
|
||||
├── erofs_fs.h - 磁盘格式定义
|
||||
└── xattr.h - 扩展属性接口
|
||||
```
|
||||
|
||||
## 分层架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ VFS 层 (FreeBSD kernel) │
|
||||
└─────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────▼───────────────────────┐
|
||||
│ VFS 接口层 │
|
||||
│ - erofs_vnops.c │
|
||||
│ - super.c (mount/unmount/root) │
|
||||
└─────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────▼───────────────────────┐
|
||||
│ 文件系统逻辑层 │
|
||||
│ - inode.c (erofs_read_inode) │
|
||||
│ - namei.c (erofs_namei) │
|
||||
│ - dir.c (erofs_readdir_block) │
|
||||
│ - xattr.c (erofs_getxattr) │
|
||||
└─────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────▼───────────────────────┐
|
||||
│ 数据访问层 │
|
||||
│ - data.c (erofs_map_blocks) │
|
||||
│ - data.c (erofs_read_data) │
|
||||
│ - zmap.c / zdata.c │
|
||||
│ - decompressor.c (z_erofs_decompress) │
|
||||
└─────────────┬───────────────────────┘
|
||||
│
|
||||
┌─────────────▼───────────────────────┐
|
||||
│ 块 I/O 层 │
|
||||
│ - erofs_bread/erofs_brelse │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 核心数据结构
|
||||
|
||||
### erofs_mount (内存中的文件系统状态)
|
||||
```c
|
||||
struct erofs_mount {
|
||||
struct mount *mnt; // FreeBSD mount 结构
|
||||
struct vnode *devvp; // 块设备 vnode
|
||||
struct g_consumer *cp; // GEOM consumer
|
||||
|
||||
uint32_t block_size; // 块大小
|
||||
uint64_t root_nid; // 根目录 NID
|
||||
uint32_t feature_compat; // 特性标志
|
||||
uint32_t feature_incompat;
|
||||
|
||||
struct erofs_sb_lz4_info lz4; // LZ4 参数
|
||||
struct erofs_deviceslot *devs; // 设备表
|
||||
struct erofs_xattr_prefix_item *xattr_prefixes; // xattr 前缀表
|
||||
};
|
||||
```
|
||||
|
||||
### erofs_node (内存中的 inode)
|
||||
```c
|
||||
struct erofs_node {
|
||||
struct vnode *vnode; // 关联的 vnode
|
||||
uint64_t nid; // 节点 ID
|
||||
uint64_t size; // 文件大小
|
||||
uint8_t datalayout; // 数据布局类型
|
||||
|
||||
// 压缩相关
|
||||
uint8_t z_algorithmformat;
|
||||
uint8_t z_lclusterbits;
|
||||
|
||||
// Chunk-based 相关
|
||||
uint16_t chunkformat;
|
||||
uint8_t chunkbits;
|
||||
|
||||
// Fragment 相关
|
||||
uint32_t fragmentoff;
|
||||
bool fragment;
|
||||
};
|
||||
```
|
||||
|
||||
## 关键实现细节
|
||||
|
||||
### 1. 数据布局支持
|
||||
|
||||
支持 4 种数据布局:
|
||||
- **FLAT_PLAIN**: 连续块
|
||||
- **FLAT_INLINE**: 最后一个逻辑块位于 inode metadata block 内,且受声明
|
||||
image/metabox bounds 约束
|
||||
- **CHUNK_BASED**: 固定大小 chunk,支持稀疏文件
|
||||
- **COMPRESSED**: 可变大小压缩 cluster
|
||||
|
||||
### 2. 压缩算法
|
||||
|
||||
支持 4 种压缩算法及未压缩 transform:
|
||||
- LZ4 (LZ4HC)
|
||||
- LZMA
|
||||
- DEFLATE
|
||||
- ZSTD
|
||||
- 未压缩
|
||||
|
||||
### 3. 高级特性
|
||||
|
||||
- ✅ **ztailpacking**: 压缩文件尾部内联
|
||||
- ✅ **fragments**: 已验证的 fragment-backed 压缩文件与 metabox carrier
|
||||
- ⚠️ **dedupe**: 仅声明已验证的 fragment/partial-reference 形式,不宣称
|
||||
覆盖所有未来编码
|
||||
- ✅ **xattr_prefixes**: 共享 xattr 前缀表
|
||||
- ✅ **device_table**: 多设备支持
|
||||
- ✅ **metabox**: 每 inode 元数据盒
|
||||
|
||||
### 4. 安全机制
|
||||
|
||||
repo22 的边界策略:
|
||||
- 所有指针操作前检查边界
|
||||
- 所有算术运算检查溢出
|
||||
- 所有分配检查大小合理性
|
||||
- 递归深度限制
|
||||
- 设备 ID 和块地址验证
|
||||
|
||||
## 与 Linux 版本的差异
|
||||
|
||||
### 对照基线
|
||||
|
||||
本轮维护逐文件对照工作区中的 `/work/dev-src-linux/fs/erofs`。该目录是导入的
|
||||
Linux 7.1-rc1 EROFS 参考快照;对照不依赖 repo22 与 Linux 树具有共同 Git
|
||||
历史。`/work/linux-src/fs/erofs` 中对应文件与该精简快照字节一致,但不是本轮
|
||||
文件映射的依据。
|
||||
|
||||
### 必要差异(FreeBSD 适配)
|
||||
|
||||
1. **内存分配**:使用 `malloc(..., M_EROFS, ...)` 而非 `kmalloc()`
|
||||
2. **块 I/O**:通过 GEOM consumer 和 FreeBSD vnode/buffer 接口读取 provider
|
||||
3. **VFS 接口**:`erofs_vnops.c` 实现 FreeBSD `vop_vector`,不照搬 Linux
|
||||
`inode_operations`、folio 或 iomap 接口
|
||||
4. **错误约定**:内核入口返回正的 FreeBSD errno;Linux 负 errno 或
|
||||
`ERR_PTR` 仅作为算法对照,不能机械移植
|
||||
5. **压缩后端**:BSD 调度器跨编译单元调用 `internal.h` 中的简单后端 API;
|
||||
Linux 使用 `struct z_erofs_decompressor` 和不同的内存/页面生命周期
|
||||
6. **LZ4 文件职责**:BSD 保留独立 `decompressor_lz4.c` 有界解码器;Linux LZ4 路径位于
|
||||
`decompressor.c` 并依赖 Linux 内核 LZ4/page API
|
||||
7. **平台特性**:Linux `sysfs.c`、`fileio.c`、`fscache.c`、`ishare.c` 和
|
||||
`zutil.c` 没有无条件对应物,不为文件外观引入空包装
|
||||
8. **构建架构**:当前只验证 FreeBSD 15 amd64,Makefile 明确拒绝其他
|
||||
`MACHINE_ARCH`
|
||||
|
||||
### 保持一致的部分
|
||||
|
||||
- 静态目录 helper 使用 Linux 名称 `find_target_dirent`
|
||||
- LZMA、DEFLATE、ZSTD 后端使用 Linux 文件名 `decompressor_*.c`
|
||||
- Makefile 先列 metadata/VFS 文件,再列压缩调度、映射和后端文件
|
||||
- 跨文件后端声明集中在 `internal.h`,不在调用方手写 `extern`
|
||||
- `erofs_fs.h` 的磁盘格式定义和核心目录/映射算法按 Linux 语义核对
|
||||
|
||||
## 代码规范
|
||||
|
||||
### 命名约定
|
||||
- 公共函数:`erofs_<module>_<action>`
|
||||
- 静态函数:描述性名称,无固定前缀
|
||||
- 宏:`EROFS_*` 全大写
|
||||
- 结构体:`struct erofs_*`
|
||||
|
||||
### 函数排序(每个文件)
|
||||
1. 辅助函数(static)
|
||||
2. 核心逻辑函数
|
||||
3. VFS 接口函数
|
||||
4. 模块注册/清理(仅 super.c)
|
||||
|
||||
### 错误处理
|
||||
```c
|
||||
int erofs_function(...)
|
||||
{
|
||||
int error = 0;
|
||||
void *buf = NULL;
|
||||
|
||||
// 操作...
|
||||
if (条件) {
|
||||
error = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// ...
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (buf)
|
||||
erofs_brelse(buf);
|
||||
return error;
|
||||
}
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
|
||||
不存在受支持的用户态单元测试入口。旧的 `src/Makefile.test`、
|
||||
`tests/test_decompress.c` 和 `tests/test_decompress_standalone.c` 尝试把内核解压
|
||||
源码按不匹配的用户态 ABI 链接;这些入口均已退役并删除,不能作为可运行测试或
|
||||
feature 验证证据。
|
||||
|
||||
旧的 `test_super.c` 和 `test_inode.c` 只重复了测试文件中的公式,并未调用
|
||||
内核生产解析路径,其中 inode harness 还引用过已删除的磁盘字段。它们已退役,
|
||||
不得作为 feature 验证证据。superblock、inode、pager 和错误路径必须使用
|
||||
`TC*.md` 中的确定性镜像,经 FreeBSD 内核模块实际挂载或访问验证。
|
||||
|
||||
### 集成测试
|
||||
|
||||
仓库根目录遗留的 `test_all_decompress.sh` 和 `test_chunk_based.sh` 包含其他
|
||||
repo 的硬编码路径,不能作为 repo22 的测试入口或验收证据。受支持的验证方式是
|
||||
直接执行 `tests/TC*.md` 中记录的 FreeBSD 15 内核步骤,并将命令、errno、哈希和
|
||||
清理状态写入 `tests/results/manual/` 下的日期报告。
|
||||
|
||||
### VM 测试
|
||||
- 挂载真实镜像
|
||||
- 文件读取验证
|
||||
- 性能基准测试
|
||||
|
||||
## 维护指南
|
||||
|
||||
### 同步上游 Linux 变更
|
||||
|
||||
1. 选定明确的 Linux `fs/erofs` 快照;当前工作区基线为
|
||||
`/work/dev-src-linux/fs/erofs`
|
||||
2. 逐文件识别修改,不假设两个实现共享提交历史
|
||||
3. 检查是否为磁盘格式变更(`erofs_fs.h`)或 Linux 专属 VFS/page API
|
||||
4. 只移植语义上适用的算法,并保留 FreeBSD errno、锁、GEOM 和 vnode 约定
|
||||
5. 运行双配置构建、模块加载和真实镜像挂载测试
|
||||
|
||||
### 添加新特性
|
||||
|
||||
1. 在 `erofs_fs.h` 添加磁盘格式定义
|
||||
2. 在 `internal.h` 添加内存结构
|
||||
3. 实现解析逻辑(data.c/inode.c)
|
||||
4. 添加确定性 fixture 和对应的 `TC*.md` 内核测试
|
||||
5. 更新文档
|
||||
|
||||
## 性能考虑
|
||||
|
||||
- **零拷贝**:直接从缓冲区缓存读取
|
||||
- **延迟加载**:仅在需要时读取 inode 元数据
|
||||
- **缓存友好**:利用 FreeBSD 的 vnode 缓存
|
||||
- **批量操作**:目录读取一次性处理多个条目
|
||||
|
||||
## 已知限制
|
||||
|
||||
- 不支持写操作(只读文件系统)
|
||||
- 不支持 FUSE 模式
|
||||
- 构建和运行时验证目前仅覆盖 FreeBSD 15 amd64
|
||||
- 不实现 Linux file-backed、fscache、page-cache sharing 或 sysfs 控制面
|
||||
Reference in New Issue
Block a user