Skip to content

构建新虚拟文件系统axvfs #343

Description

@Josen-B

https://github.com/arceos-hypervisor/axvfs

设计目标

创建一个统一、通用、功能完整的 VFS,要求:

​ ✅ 支持相对路径操作(通过文件/目录句柄)

​ ✅ 提供完整的元数据接口

​ ✅ 支持软链接和硬链接

​ ✅ 解决并发访问问题

​ ✅ 通用性:三个平台都能方便接入

​ ✅ 简洁性:接口设计清晰,易于实现

结合 axfs_vfs 和 axfs-ng-vfs,实现统一的虚拟文件系统 axvfs,具有标准通用的接口,arceos,starry和axvisor 分别实现对应的 api 层接入 axvfs。

Image

对文件或路径的操作依然通过std进入arceos_api,然后下层的实现是一套统一的实现方案。

如果有对于starry或axvisor特有的结构或接口,可以通过feature (monolithic & hypervisor)控制。

代码结构

axvfs/
├── Cargo.toml
├── README.md          # 使用指南
└── src/
    ├── file_handle.rs # 文件句柄
    ├── dir_handle.rs  # 目录句柄
    ├── types.rs       # 核心类型
    ├── traits.rs      # Trait 定义
    ├── path.rs        # 路径操作
    ├── mount.rs       # 挂载管理
    └── lib.rs         # 主库文件

核心模块设计

1. 核心类型 (types.rs)

定义文件系统的基础类型:

// 节点类型
pub enum NodeType {
    RegularFile, Directory, Symlink,
    CharDevice, BlockDevice, Fifo, Socket
}

// 权限模式 (POSIX 风格)
pub struct NodePermission: u16 {
    OWNER_READ, OWNER_WRITE, OWNER_EXEC,
    GROUP_READ, GROUP_WRITE, GROUP_EXEC,
    OTHER_READ, OTHER_WRITE, OTHER_EXEC,
    SET_UID, SET_GID, STICKY
}

// 完整元数据
pub struct Metadata {
    device: u64,           // 设备 ID
    inode: u64,            // inode 号
    nlink: u64,            // 硬链接计数
    mode: NodePermission,  // 权限
    node_type: NodeType,   // 节点类型
    uid: u32,              // 所有者用户 ID
    gid: u32,              // 所有者组 ID
    size: u64,             // 大小
    block_size: u64,       // 块大小
    blocks: u64,           // 分配的块数
    rdev: DeviceId,        // 设备 ID(特殊文件)
    atime: Duration,       // 访问时间
    mtime: Duration,       // 修改时间
    ctime: Duration,       // 状态改变时间
}

2. 核心 Trait (traits.rs)

FilesystemOps Trait

文件系统操作接口:

pub trait FilesystemOps: Send + Sync {
    fn name(&self) -> &str;                           // 文件系统名称
    fn statfs(&self) -> VfsResult<FileSystemInfo>;    // 文件系统统计
    fn sync(&self) -> VfsResult<()>;                  // 同步
    fn mount(&self, mount_point: &str) -> VfsResult<()>; // 挂载
    fn unmount(&self) -> VfsResult<()>;               // 卸载
    fn root(&self) -> Arc<dyn VnodeOps>;              // 根目录
}

VnodeOps Trait

虚拟节点操作接口:

pub trait VnodeOps: Send + Sync + Any {
    // 基本信息
    fn filesystem(&self) -> &Arc<dyn FilesystemOps>;
    fn inode(&self) -> u64;
    fn node_type(&self) -> NodeType;
    fn metadata(&self) -> VfsResult<Metadata>;
    fn set_metadata(&self, update: MetadataUpdate) -> VfsResult<()>;
    fn parent(&self) -> VfsResult<Option<Arc<dyn VnodeOps>>>;
    fn sync(&self, data_only: bool) -> VfsResult<()>;

    // 文件操作
    fn read_at(&self, offset: u64, buf: &mut [u8]) -> VfsResult<usize>;
    fn write_at(&self, offset: u64, buf: &[u8]) -> VfsResult<usize>;
    fn truncate(&self, size: u64) -> VfsResult<()>;

    // 目录操作
    fn lookup(&self, name: &str) -> VfsResult<Arc<dyn VnodeOps>>;
    fn create(&self, name: &str, node_type: NodeType, mode: NodePermission)
        -> VfsResult<Arc<dyn VnodeOps>>;
    fn remove(&self, name: &str) -> VfsResult<()>;
    fn link(&self, name: &str, target: &Arc<dyn VnodeOps>) -> VfsResult<()>;
    fn unlink(&self, name: &str) -> VfsResult<()>;
    fn symlink(&self, name: &str, target: &str) -> VfsResult<()>;
    fn readlink(&self) -> VfsResult<String>;
    fn rename(&self, old_name: &str, new_dir: &Arc<dyn VnodeOps>, new_name: &str)
        -> VfsResult<()>;
    fn readdir(&self, offset: usize, sink: &mut dyn DirEntrySink) -> VfsResult<usize>;
    fn mkdir(&self, name: &str, mode: NodePermission) -> VfsResult<Arc<dyn VnodeOps>>;
    fn rmdir(&self, name: &str) -> VfsResult<()>;
}

3. 文件/目录句柄 (file_handle.rs, dir_handle.rs)

FileHandle

支持位置跟踪的文件描述符:

pub struct FileHandle {
    vnode: Vnode,                      // 关联的 vnode
    offset: AtomicU64,                 // 当前位置(原子操作,并发安全)
    flags: OpenFlags,                  // 打开标志
    id: u64,                          // 句柄 ID
}

impl FileHandle {
    pub fn read(&self, buf: &mut [u8]) -> VfsResult<usize>;
    pub fn write(&self, buf: &[u8]) -> VfsResult<usize>;
    pub fn seek(&self, offset: i64, whence: u8) -> VfsResult<u64>;
    pub fn truncate(&self, size: u64) -> VfsResult<()>;
    pub fn sync(&self, data_only: bool) -> VfsResult<()>;
}

DirHandle

支持相对路径操作的目录描述符:

pub struct DirHandle {
    vnode: Vnode,                      // 关联的目录 vnode
    offset: AtomicU64,                 // 读取位置
    id: u64,
}

impl DirHandle {
    // 相对路径操作
    pub fn lookup(&self, name: &str) -> VfsResult<Vnode>;
    pub fn create_file(&self, name: &str, mode: NodePermission)
        -> VfsResult<Vnode>;
    pub fn create_dir(&self, name: &str, mode: NodePermission)
        -> VfsResult<Vnode>;
    pub fn readdir(&self) -> VfsResult<Vec<DirEntry>>;
    pub fn symlink(&self, name: &str, target: &str) -> VfsResult<()>;
    pub fn readlink(&self, name: &str) -> VfsResult<String>;
    pub fn rename(&self, old_name: &str, new_dir: &DirHandle, new_name: &str)
        -> VfsResult<()>;
}

相对路径示例:

// openat 等价操作
fn sys_openat(dirfd: i32, path: &str, flags: OpenFlags) -> VfsResult<i32> {
    let vnode = if path.starts_with('/') {
        // 绝对路径
        mount_mgr.lookup(Path::new(path))?
    } else {
        // 相对路径 - 使用 dir_handle
        let dir_handle = dir_table.get(dirfd as usize)?;
        dir_handle.lookup(path)?
    };
    Ok(file_table.insert(FileHandle::new(vnode, flags)?)? as i32)
}

4. 路径操作 (path.rs)

完整的路径解析和操作功能:

pub struct Path {
    inner: str,
}

pub struct PathBuf {
    inner: String,
}

impl Path {
    pub fn components(&self) -> Components;
    pub fn parent(&self) -> Option<&Path>;
    pub fn file_name(&self) -> Option<&str>;
    pub fn join(&self, path: &Path) -> PathBuf;
    pub fn normalize(&self) -> PathBuf;  // 处理 . 和 ..
    pub fn is_absolute(&self) -> bool;
}

5. 挂载管理 (mount.rs)

管理多个文件系统的挂载和路径解析:

pub struct MountManager {
    mounts_by_device: Mutex<BTreeMap<u64, Arc<MountPoint>>>,
    mounts_by_path: Mutex<BTreeMap<String, Arc<MountPoint>>>,
    root_mount: Mutex<Option<Arc<MountPoint>>>,
}

impl MountManager {
    pub fn set_root(&self, filesystem: Arc<dyn FilesystemOps>) -> VfsResult<()>;
    pub fn mount(&self, mount_path: &Path, filesystem: Arc<dyn FilesystemOps>)
        -> VfsResult<Arc<MountPoint>>;
    pub fn unmount(&self, mount_path: &Path) -> VfsResult<()>;
    pub fn resolve_mount(&self, path: &Path) -> VfsResult<Arc<MountPoint>>;
    pub fn lookup(&self, path: &Path) -> VfsResult<Vnode>;
    pub fn statfs(&self, path: &Path) -> VfsResult<FileSystemInfo>;
    pub fn build_path(&self, mount: &MountPoint, vnode: &Vnode) -> VfsResult<PathBuf>;
}

关键实现:

  • resolve_mount(): 查找最长匹配的挂载点
  • lookup(): 解析路径到 vnode,支持挂载点跨越
  • build_path(): 从 vnode 向上遍历构建完整路径,用于目录句柄的相对路径操作

6. 文件表和目录表 (file_handle.rs, dir_handle.rs)

管理打开的文件和目录描述符:

pub struct FileTable {
    handles: Mutex<Vec<Option<Arc<FileHandle>>>>,
}

impl FileTable {
    pub fn new() -> Self;
    pub fn insert(&self, file: FileHandle) -> VfsResult<usize>;
    pub fn get(&self, fd: usize) -> VfsResult<Arc<FileHandle>>;
    pub fn remove(&self, fd: usize) -> VfsResult<()>;
}

pub struct DirTable {
    handles: Mutex<Vec<Option<Arc<DirHandle>>>>,
}

impl DirTable {
    pub fn new() -> Self;
    pub fn insert(&self, dir: DirHandle) -> VfsResult<usize>;
    pub fn get(&self, fd: usize) -> VfsResult<Arc<DirHandle>>;
    pub fn remove(&self, fd: usize) -> VfsResult<()>;
}

特性:

  • 线程安全的句柄管理
  • 支持 fd 分配和释放
  • 支持句柄克隆和共享

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions