Files
erofs-freebsd-out-tree/docs/architecture.md
T
2026-08-13 10:44:59 +02:00

284 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 - 压缩配置解析和统一调度
├── 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 - 扩展属性接口
└── erofs_defs.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 errnoLinux 负 errno 或
`ERR_PTR` 仅作为算法对照,不能机械移植
5. **压缩后端**BSD 调度器跨编译单元调用 `internal.h` 中的简单后端 API
Linux 使用 `struct z_erofs_decompressor` 和不同的内存/页面生命周期
6. **LZ4 文件职责**BSD 保留独立 `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 amd64Makefile 明确拒绝其他
`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` 从错误目录引用
`test_decompress.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 控制面