os/fs/ext4/
mod.rs

1//! Ext4 - Linux Ext4 文件系统支持
2//!
3//! 该模块提供了与 **Linux Ext4 文件系统兼容** 的读写支持,基于 `ext4_rs` crate 实现。
4//!
5//! # 组件
6//!
7//! - [`Ext4FileSystem`] - 文件系统结构,实现 `FileSystem` trait
8//! - [`Ext4Inode`] - Inode 包装,将 `ext4_rs` 操作映射到 VFS
9//! - [`BlockDeviceAdapter`] - 块设备适配器,桥接 VirtIO 和 ext4_rs
10//!
11//! # 设计概览
12//!
13//! ## 适配层架构
14//!
15//! ```text
16//! VFS (Inode trait)
17//!       ↓
18//! Ext4Inode (包装层)
19//!       ↓
20//! ext4_rs::Ext4 (第三方库)
21//!       ↓
22//! BlockDeviceAdapter
23//!       ↓
24//! BlockDriver (VirtIO Block)
25//! ```
26//!
27//! ## 支持的操作
28//!
29//! - **文件操作**:read、write、truncate、sync
30//! - **目录操作**:lookup、create、mkdir、readdir、rmdir
31//! - **链接操作**:symlink、link、unlink、readlink
32//! - **元数据**:chmod、chown、set_times
33//! - **重命名**:rename(支持跨目录移动)
34//!
35//! # 使用示例
36//!
37//! ```rust
38//! use crate::fs::init_ext4_from_block_device;
39//!
40//! // 从第一个块设备挂载 ext4 为根文件系统
41//! init_ext4_from_block_device()?;
42//!
43//! // 读写文件
44//! let content = vfs_load_file("/bin/hello")?;
45//! ```
46//!
47//! # 配置要求
48//!
49//! - **块大小**:必须为 4096 字节(与 `mkfs.ext4 -b 4096` 匹配)
50//! - **块设备**:需要支持 VirtIO Block 或兼容驱动
51//!
52//! # 限制
53//!
54//! - `mknod` 未实现(设备文件创建)
55//! - 非日志模式,崩溃可能导致不一致
56pub mod adpaters;
57pub mod inode;
58
59pub use adpaters::BlockDeviceAdapter;
60pub use inode::Ext4Inode;
61
62use crate::device::block::BlockDriver;
63use crate::pr_info;
64use crate::sync::Mutex;
65use crate::vfs::{FileSystem, FsError, Inode, StatFs};
66use alloc::sync::Arc;
67
68/// Ext4 文件系统
69pub struct Ext4FileSystem {
70    /// 底层块设备驱动
71    device: Arc<dyn BlockDriver>,
72
73    /// 块大小
74    block_size: usize,
75
76    /// 总块数
77    total_blocks: usize,
78
79    /// 设备 ID
80    device_id: usize,
81
82    /// ext4_rs 文件系统对象
83    ext4: Arc<Mutex<ext4_rs::Ext4>>,
84
85    /// 根 inode
86    root: Arc<dyn Inode>,
87}
88
89impl Ext4FileSystem {
90    /// 打开 Ext4 文件系统
91    ///
92    /// # 参数
93    /// - `device`: 块设备驱动
94    /// - `block_size`: 块大小
95    /// - `total_blocks`: 总块数
96    /// - `device_id`: 设备 ID
97    ///
98    /// # 返回
99    /// Ext4 文件系统实例
100    pub fn open(
101        device: Arc<dyn BlockDriver>,
102        block_size: usize,
103        total_blocks: usize,
104        device_id: usize,
105    ) -> Result<Arc<Self>, FsError> {
106        pr_info!("[Ext4] Opening Ext4 filesystem on block device");
107        pr_info!(
108            "[Ext4] Device block size: {}, total blocks: {}",
109            block_size,
110            total_blocks
111        );
112
113        // 创建适配器
114        let adapter = Arc::new(BlockDeviceAdapter::new(device.clone(), block_size));
115
116        // 使用 ext4_rs 打开文件系统
117        // 注意:ext4_rs::Ext4::open 直接返回 Ext4,不返回 Result
118        pr_info!("[Ext4] Calling ext4_rs::Ext4::open...");
119        let ext4 = ext4_rs::Ext4::open(adapter);
120        pr_info!("[Ext4] ext4_rs returned successfully");
121
122        let ext4 = Arc::new(Mutex::new(ext4));
123
124        // 创建根 inode (inode 号 2 是 Ext4 的根目录)
125        let root = Arc::new(Ext4Inode::new(ext4.clone(), 2));
126
127        let fs = Arc::new(Ext4FileSystem {
128            device,
129            block_size,
130            total_blocks,
131            device_id,
132            ext4,
133            root,
134        });
135
136        pr_info!("[Ext4] Filesystem opened successfully");
137        Ok(fs)
138    }
139}
140
141impl FileSystem for Ext4FileSystem {
142    fn fs_type(&self) -> &'static str {
143        "ext4"
144    }
145
146    fn root_inode(&self) -> Arc<dyn Inode> {
147        self.root.clone()
148    }
149
150    fn sync(&self) -> Result<(), FsError> {
151        // 调用底层块设备的 flush 方法,将缓存刷新到磁盘
152        if self.device.flush() {
153            Ok(())
154        } else {
155            Err(FsError::IoError)
156        }
157    }
158
159    fn statfs(&self) -> Result<StatFs, FsError> {
160        let ext4 = self.ext4.lock();
161        let sb = &ext4.super_block;
162
163        Ok(StatFs {
164            block_size: self.block_size,
165            total_blocks: self.total_blocks,
166            free_blocks: sb.free_blocks_count() as usize,
167            available_blocks: sb.free_blocks_count() as usize,
168            total_inodes: sb.inodes_count as usize,
169            free_inodes: sb.free_inodes_count() as usize,
170            fsid: self.device_id as u64,
171            max_filename_len: 255, // EXT4_NAME_LEN
172        })
173    }
174}