Conversation
- Introduced `fs.rs` to manage filesystem context, including root and current directory handling. - Added functionality for resolving paths, reading, writing, and managing directories and files. - Implemented symlink resolution with a limit on the number of symlinks followed. - Created a registry for filesystem contexts to support task-local storage and root pivoting. - Added `ReadDir` iterator for directory entries. - Created `mod.rs` to organize and expose the `file` and `fs` modules.
- Updated Cargo.toml to streamline filesystem dependencies by removing redundant entries and introducing new features for ext4 and fat filesystems. - Modified board configuration files to eliminate the "fs" feature where it was no longer necessary. - Adjusted tests and build scripts to reflect the removal of the "fs" feature, ensuring compatibility with the new filesystem structure. - Introduced a new `fs_policy.rs` file to manage filesystem detection and initialization, enhancing the overall organization and clarity of the filesystem handling logic.
- Added a new module `discovery.rs` to handle the discovery of filesystems on block devices. - Introduced `RootSelectionPolicy` to define rules for selecting the root filesystem when no explicit boot arguments are provided. - Updated `lib.rs` to include the new discovery module and its functionalities. - Modified `Cargo.toml` to enable filesystem features by default. - Enhanced the initialization process for filesystems to support automatic detection and selection based on the defined policy.
# Conflicts: # os/axvisor/configs/board/phytiumpi.toml # os/axvisor/configs/board/roc-rk3568-pc.toml
…hytiumPi and ROC-RK3568
There was a problem hiding this comment.
PR #943 Review — 文件系统栈重构(axfs-ng → axfs 统一)
总体评价:✅ Approve
这是一次非常高质量的大规模重构(205 文件,+3169/-8189),将 axfs-ng/axfs-ng-vfs 合并为统一的 axfs/axfs-vfs,架构清晰,文档详尽。
架构变更亮点
-
模块划分清晰:
block.rs(块设备抽象)、discovery.rs(卷发现与挂载)、highlevel/fs.rs(FsContext 全局状态)、highlevel/file.rs(文件抽象与页缓存)各司其职,职责边界明确。 -
Mount 传播修复(
mount.rs):使用独立副本替代共享Arc,解决了 bind mount 和pivot_mount时的传播语义问题,这是正确的设计。 -
POSIX 语义改进:
O_PATH支持(不实际打开文件)- append 写入锁下沉到 inode 级别,避免多 fd 间的竞态
- 正确处理尾随斜杠和空路径的
openat语义
-
ramfs rename 重写:从递归实现改为栈式迭代,避免内核栈溢出风险。
-
FAT 时间转换:不再对无效日期
panic,改为静默降级。 -
rsext4 拼写修正:
inodetable_cahce→inodetable_cache。 -
消除重复 crate:完全移除了
axfs-ng-vfs,统一为axfs-vfs。
本地验证结果
| 检查项 | 结果 |
|---|---|
cargo fmt --check |
✅ 通过 |
clippy --package ax-fs-vfs |
✅ 通过 |
clippy --package ax-fs-ramfs |
✅ 通过 |
clippy --package ax-fs |
✅ 通过(10/10) |
clippy --package rsext4 |
✅ 通过(2/2) |
clippy --package ax-api |
✅ 通过(13/13) |
重叠分析
已扫描仓库全部 open PR,未发现与文件系统栈相关的重叠 PR。其他 open PR(#892 eBPF JIT、#961 RISC-V 动态平台等)均与本 PR 无关。
CI 状态
PR 已合并(2026-05-26)。CI 中 Release-plz release 的失败与本次代码变更无关(Release 自动化问题),其余 lint/format 检查通过或被跳过。
总结
一次非常出色的基础设施重构。代码质量高,PR 文档堪称范本(~5000 字的详细设计说明)。所有本地静态检查均通过,无阻塞问题。建议 approve。
Powered by glm-5.1
文件系统栈重构 PR 说明
1. 背景与问题
对于整个 fs,旧的实现以
axfs::fops和若干分散的 helper 为核心,能支撑基本std::fs场景,但整体仍停留在较扁平的文件操作封装阶段:VFS 节点模型、mount tree、rootfs 发现、分区扫描、文件缓存、POSIX 元数据和上层 API 语义之间边界不够清晰。随着 StarryOS、Axvisor、ArceOS std、动态 rootfs 和多文件系统格式同时推进,旧结构已经很难继续扩展。第一,VFS 抽象过薄。
dev上的axfs_vfs主要围绕旧的VfsNodeOps/VfsDirEntry/VfsNodeRef工作,目录、文件、元数据、路径解析和 mount 关系没有形成稳定的对象模型。上层依赖fops做大量包装,导致 rename、mount、stat、symlink、directory fd 等语义需要在不同层重复处理。第二,mount tree 能力不足。旧代码有
mounts.rs,但没有完整的Mountpoint/Location模型,也缺少 per-location 的 mountpoint children、readonly、propagation、pivot/move/bind 这类可组合状态。StarryOS 需要更接近 Linux 的 mount 行为时,旧模型只能继续堆逻辑,难以表达“同一个 DirEntry 在不同 mountpoint 下的位置”和“mount root / parent location”的关系。第三,rootfs 初始化逻辑集中且难复用。
dev里 rootfs 相关逻辑分散在root.rs、partition.rs、dev.rs等文件中,block device、分区扫描、filesystem 构造、root 选择和 mount 初始化耦合在一起。对于 runtime 自动启动这是可用的,但对于测试、Starry、Axvisor 或已经构造好Filesystem的调用方来说,不能直接复用“初始化 root filesystem context”这一步。第四,block device 与 partition region 抽象不够统一。旧代码分别处理 FAT/ext4 device、partition reader 和 root 选择,没有把“共享物理设备”和“某个 filesystem 可见的 LBA region”提升成公共 API。后续要暴露 discovered filesystems、挂载非 root 分区或复用同一个物理 block device 时,会遇到重复包装和所有权传递问题。
第五,高层 file API 和底层 filesystem 适配耦合。旧
fops.rs同时承担File、Directory、OpenOptions、metadata 映射和一部分 API 语义。它没有 page cache 层,也没有更明确的FileBackend区分。普通文件、目录、设备文件、socket/fifo、O_PATH、O_APPEND 等语义容易互相影响。第六,POSIX / ArceOS API 语义不够稳定。旧实现对 stat、getdents、directory fd、默认目录权限、feature 暴露等行为没有统一地落在新的 highlevel/VFS 模型上。迁移过程中如果只做结构替换,很容易出现 inode/uid/gid/blksize 被硬编码、目录 fd 失去真实 location、getdents 部分读取语义丢失等兼容性回退。
第七,底层文件系统适配较粗。
dev上 FAT 和 ext4 适配以fatfs.rs、ext4fs.rs这类大文件为主,不利于把 disk、file、dir、fs、util 分开测试和维护。ext4 也没有同时保留 rsext4/lwext4 两种后端的清晰模块边界。因此,本 PR 进行了一次文件系统栈重构:用新的 VFS / highlevel / discovery 架构替换旧
fops + root/partition/dev模型,同时把迁移过程中发现的兼容性和正确性问题一并修正。2. 核心修改
2.1 总体架构
新的文件系统栈按职责拆成以下层级:
和
dev旧代码相比,最重要的变化是:os/arceos/modules/axfs/src/fops.rsapi/dir.rs、api/file.rs、mounts.rs、partition.rs、root.rs、dev.rsblock.rs、discovery.rshighlevel/file.rs、highlevel/fs.rsfs/fat/*、fs/ext4/{rsext4,lwext4}/*mount.rs、node/{dir,file,mod}.rs、path.rs、types.rs新入口把“从 block devices 自动发现 rootfs”和“直接使用已构造 filesystem 初始化 root”分开:
init_filesystems()面向 runtime 自动启动路径,负责扫描设备、选择 root、构造 filesystem;init_root_filesystem()面向上层已经拿到Filesystem的场景,直接初始化全局FsContext。这使 Starry、Axvisor 和测试不需要被迫经过 block discovery。2.2 ArceOS / StarryOS / Axvisor 引用路径
本 PR 不是只替换
axfs内部实现。axfs和axfs_vfs是 ArceOS、StarryOS、Axvisor 共同依赖的基础文件系统层,并且每个 OS 的入口不止一条。迁移时需要同时保证 runtime 初始化、std/posix API、Starry syscall、pseudofs、Axvisor shell/config/image 这些路径都落到同一套 highlevel/VFS 语义上。ArceOS 的主要引用路径如下:
这条路径负责系统启动时从 virtio-blk、ramdisk 或平台 block device 中发现 rootfs。相关 feature 在
os/arceos/modules/axruntime/Cargo.toml和os/arceos/api/axfeat/Cargo.toml中传播:fs打开 runtime block 初始化,fs-fat/fs-ext4同时打开ax-fs和 runtime 侧格式支持。这条路径对应
std::fs/axstd::fs风格调用,是 ArceOS examples、Axvisor 和普通 Rust 应用最常走的接口。PR 中保留fs-apifeature 暴露,就是为了让这条路径不因为内部重构而断开。这条路径服务 libc/POSIX syscall 语义,重点依赖真实
Metadata、目录Location、ReadDir::rewind()和NodeType as d_type。因此本 PR 在迁移结构的同时恢复 stat/getdents/lseek(directory) 等稳定语义。Unix domain socket bind/open 会经过
FS_CONTEXT.resolve()和OpenOptions.open(),所以特殊节点、socket 类型、path resolve 的行为也必须和普通文件路径共享同一套 VFS 规则。StarryOS 的引用路径更分散,因为 Starry 既直接使用
ax_fs,又直接构造大量ax_fs_vfs节点:这是 Starry 内核自己的
FileLike/ fd table 包装层。普通文件、目录、memfd、mmap backend 都会在这里把ax_fs::File或FileBackend转换成 Starry 的 fd 对象。这条路径覆盖 open/openat、read/write、mkdir/rename/chdir/sync、stat/lstat/fstat、memfd 等 syscall。它依赖新的
FsContext进行 cwd/root path resolve,也依赖Location保留目录 fd 的真实挂载位置。这条路径不是启动 rootfs discovery,而是运行时 mount 路径:Starry 可以把 loop 设备包装成
FsBlockDevice,指定BlockRegion和FilesystemKind构造 ext4 filesystem,再挂到当前 mount tree。新的公共FsBlockDevice/BlockRegion/MountpointAPI 主要就是为了支撑这种复用。这条路径负责解析可执行文件、解释器、动态链接器和 file-backed mmap。它直接依赖
CachedFile、FileBackend和 task-localFS_CONTEXT,所以 page cache、append lock、dirty page 日志和 path resolve 变更都会影响 Starry 进程加载性能与正确性。这条路径由 Starry 自己实现 procfs、sysfs、tmpfs、debugfs、devfs 等伪文件系统节点,再挂入全局 root。它不一定经过
axfs的 FAT/ext4 适配,但必须和axfs_vfs的Filesystem、DirEntry、Mountpoint、Location模型兼容。Unix socket bind、系统信息路径解析等零散入口也直接依赖
FS_CONTEXT,因此不能只验证syscall/fs/*。Axvisor 当前主要通过
std::fs/ax_std::fs间接使用文件系统,没有像 Starry 那样直接操作ax_fs_vfsmount tree,但也有多条入口:这条路径从
/guest/vm_default读取 VM 配置目录和.toml文件,依赖read_dir()、metadata、open/read 的 std 语义。这条路径读取 guest kernel / image 内容,主要依赖
File::open()和read_exact()。因此 page cache、direct backend 和底层 FAT/ext4 read 路径都会影响 VM 镜像加载。这条路径是交互式 shell 对文件系统的引用。它走 std facade,但覆盖目录枚举、metadata、文件类型、权限 mode、读文件等更接近用户态工具的行为,所以也是验证
getdents、stat和NodeType映射的重要入口。2.3 VFS:从节点引用模型升级为 Mountpoint / Location 模型
axfs_vfs现在提供更明确的对象层级。DirEntry表示一个 filesystem 内的目录项,持有:Node::File或Node::DirNodeTypeReferenceLocation表示某个DirEntry在某个Mountpoint下的位置。这样同一个 filesystem entry 可以在不同 mountpoint 中出现,而路径解析、absolute path、mount parent、readonly 状态都可以通过Location表达。Mountpoint表示 mount tree 上的一个挂载点,包含:DirEntry这比旧
mounts.rs更适合表达 bind mount、move mount、pivot root、readonly propagation 等组合行为。本 PR 同时修复了 mount propagation 的一个关键正确性问题。传播 mount 到 peers/slaves 时不再复用同一个
Arc<Mountpoint>,而是创建独立 bind replica:这避免不同 peer 共享同一个 mountpoint 的
children、location、readonly等状态。rename 后 VFS cache 也做了修正。目录 rename 后不再把旧目录 cache 直接搬到新 entry,因为旧 cache 中子
DirEntry的 parent reference 仍指向旧路径。现在保留 user data 和 mountpoint,丢弃旧 cache,让后续 lookup 从底层 FS 重建正确 parent。2.4 Block Device、Partition Region 与 Rootfs Discovery
block.rs提供公共块设备接口:SharedBlockDevice让 discovery、root filesystem 构造和后续 discovered mount 共享同一个物理设备:BlockRegion描述某个 filesystem 可见的 LBA 范围,RegionBlockDevice<T>将 region 内相对 block 映射为物理 block,并做边界检查。VolumeReader适配rd-block-volume,用于 GPT/MBR/raw 扫描。discovery.rs接管旧root.rs/partition.rs的职责,但拆成更清晰的阶段:DiscoveredDiskrd-block-volume扫描 raw/GPT/MBR volumesroot=RootSelectionPolicy选择 rootinit_root_filesystem(fs)支持的 root 参数包括:
/dev/mmcblkXpY/dev/sdXNPARTUUID=...PARTLABEL=...默认选择策略:
默认优先唯一
rootfslabel;否则允许唯一受支持分区;再否则允许唯一 raw device。这样既能支持当前 FAT raw disk 测试资产,也能支持后续 ext4/partition rootfs。discovered disks 保存时避免了旧写法的整体 clone,只 clone 选中的
selected并按原位置插回列表,保持枚举顺序。2.5 High-Level FS API:替代旧 fops
旧
fops.rs被拆成两个 highlevel 模块:highlevel/fs.rs:FsContext、current dir、path resolve、read_dir、metadata、create/remove/renamehighlevel/file.rs:OpenOptions、OpenResult、File、FileBackend、CachedFileFsContext是上层共享的路径上下文,持有 root/current directory。它替代旧 API 层直接操作全局路径字符串的方式,使 Starry/ArceOS/Axvisor 可以使用同一套 root/current dir 语义。FileBackend显式区分 cached 与 direct:普通文件默认可走 page cache;设备、FIFO、socket、path-only handle、direct option 或
NON_CACHEABLE节点走 direct。这样旧fops中混在一起的普通文件和特殊文件语义被拆开。page cache 由
CachedFileShared承载。同一 inode 的 cached handles 共享 page cache 和 append lock:之前 append lock 若放在 handle 上,多次打开同一文件后会出现并发 append 覆盖:两个 handle 都读到相同 EOF,然后写入相同 offset。现在 append offset 选择在同一 inode 级别串行化。
O_PATH入口也被补通。OpenOptions::path(true)不再因为 read/write/append 都为 false 被拒绝:随后统一附加
FileFlags::PATH。实际 I/O 会被File::is_path()拒绝,但 path-only handle 可以用于保存位置、绕过部分 open-time 检查。PageCache::Drop对 dirty page 未刷写的情况从warn!提升到error!,让真实数据丢失风险在日志和 CI 中更容易被捕获。2.6 POSIX / ArceOS API 迁移
arceos_api不再 re-export 旧fops类型,而是基于新的ax_fs::{File, OpenOptions, ReadDir}和ax_fs_vfs::Metadata提供稳定 API。arceos_posix_api的文件层也迁移到新 highlevel API:File包装ax_fs::FileDirectory保存真实Location和ReadDirstat()从真实Metadata构造getdents64写入真实 inode、offset、node typefile_type_to_d_type()直接返回NodeType as u8lseek(fd, 0, SEEK_SET)重置读取位置ReadDir新增:这覆盖 libc
rewinddir()常见实现。axstdfeature 也做了同步:fs-api下继续暴露axstd::fs和 current dir API,避免迁移后已有调用者因为 feature 切分变化而失效。2.7 具体文件系统适配
FAT 适配从旧
fatfs.rs拆为:fs/fat/disk.rs:SeekableDiskfs/fat/fs.rs:filesystem object 和 root dirfs/fat/file.rs:file node opsfs/fat/dir.rs:directory node opsfs/fat/util.rs:metadata、time、error 映射其中 FAT 时间转换不再对非法 DOS date/time
unwrap(),而是在解析失败时返回默认时间,避免坏镜像或异常元数据导致 kernel panic。ext4 适配从旧
ext4fs.rs拆为两套后端:fs/ext4/rsext4/*fs/ext4/lwext4/*rsext4 适配层去掉了
Ext4State::split()中不必要的 unsafe:同时将
inodetable_cahce修正为inodetable_cache,减少维护噪声。ramfs/devfs 也迁移到新的 VFS node API。ramfs 的 directory rename rebind 从递归改为显式栈,避免深目录树 rename 造成内核栈溢出。
3. 遗留问题与后续工作
3.1 Filesystem 全局锁与 IRQ Completion I/O
当前 FAT、rsext4、lwext4 适配层仍然依赖 filesystem 级别锁保护底层库状态。某些路径会在持有 filesystem state lock 时进入 block I/O。如果底层 block driver 使用 IRQ completion + wait queue,未来需要继续审视“持锁等待 I/O 完成”的锁顺序和中断上下文约束。
本 PR 没有把 filesystem 内部状态拆成细粒度锁,也没有引入异步 block I/O。当前目标是同步、有限步、RTOS 友好的 I/O 路径,而不是完整实现 Linux page cache / writeback / journal 调度模型。
3.2 Page Cache 错误传播仍然有限
dirty page drop 已经提升为
error!,但 page cache 仍没有完整 filesystem error state。理想情况下,writeback 或 eviction 失败后应能:fsync()/close()/ write 返回可观测错误当前只是在 drop 时暴露强日志,不会完整模拟 Linux 的 address_space error accounting。
3.3 Mount Propagation 仍是简化模型
当前 propagation 已修复“多个 peer 共享同一个 mountpoint Arc”的严重问题,但仍不是完整 Linux mount namespace / propagation 实现。仍需后续验证:
现阶段目标是保证不会发生明显的 mountpoint 状态串扰。
3.4 O_PATH 只补通入口,未实现完整 Linux 语义
O_PATH当前能成功创建 path-only handle,并通过File::is_path()拒绝实际 I/O。但完整 Linux 语义还包括更多细节,例如哪些fcntl、fstatat、openat组合允许使用 O_PATH fd。本 PR 只修复已有设计被入口封死的问题。3.5 Root Selection 仍以当前测试资产为默认
默认 root 选择仍保留“FAT raw disk 可用”的兼容路径。虽然支持 ext4 magic、partition table、PARTUUID/PARTLABEL,但本 PR 没有切换 std 默认 rootfs 到 ext4,也没有要求测试镜像迁移。后续如果统一测试资产到 ext4,需要同步调整 arceos-rust std feature 和镜像生成逻辑。
3.6 Metadata 完整性仍依赖底层 Filesystem
POSIX stat 已从硬编码恢复为真实
Metadata,但各底层 filesystem 的 metadata 仍有不完整处。例如 FAT 没有 Unix uid/gid/permission 原生语义,inode 和 blocks 也可能是近似值。这比硬编码更好,但还不是完整 POSIX 文件系统。3.7 StarryOS 与 axfs/axfs_vfs 仍存在部分重复实现
StarryOS 当前既直接使用
ax_fs::{File, OpenOptions, FS_CONTEXT, FileBackend},又在kernel/src/file/*、kernel/src/syscall/fs/*、kernel/src/pseudofs/*中维护自己的 fd 包装、目录包装、pseudofs/devfs/procfs 节点和部分 mount/syscall glue。这些实现和axfshighlevel 层、axfs_devfs、axfs_ramfs、axfs_vfs的职责存在重叠。本 PR 的处理方式是先统一接口和语义:让 StarryOS 继续通过新的
FsContext、Location、Mountpoint、FileBackend和ReadDir接入文件系统栈,避免在大重构中同时迁移所有 Starry 私有封装。后续可以继续收敛:ax_fs::File重复的逻辑下沉为可复用 helperaxfs_devfs、axfs_ramfs或新的公共 pseudo-fs crate3.8 rsext4 命名修正是源内 API 变更
inodetable_cahce已改为inodetable_cache。这是组件内部命名修复;如果外部 crate 直接访问这个 public field,可能需要同步改名。当前 workspace 内引用已经全部更新并通过 clippy。4. 验证
针对直接影响的 crate 进行了 clippy 验证: