Skip to main content

ahrightos_fs/
manager.rs

1//! 全局文件系统管理器
2//!
3//! 提供统一的文件系统访问接口,支持多文件系统挂载
4
5use super::blkfs::BlkFS;
6use super::block_dev::BlockDeviceHandle;
7use super::disk_format::{detect_disk_format, DiskFormat};
8use super::file::{FileError, FileType};
9use super::inode::Inode;
10use super::ramfs::{RamFS, RamInode};
11use super::virtualfs::{default_devtmpfs, default_procfs, default_sysfs, VirtualFileSystem};
12use alloc::string::String;
13use alloc::sync::Arc;
14use alloc::vec::Vec;
15use lazy_static::lazy_static;
16use spin::Mutex;
17
18const BASE_DIRS: [&str; 7] = ["home", "tmp", "dev", "mnt", "proc", "sys", "run"];
19
20/// BlkFS mount policy.
21///
22/// The default (`OpenOrCreate`) preserves the old teaching behavior: open an
23/// existing AhRightOS BlkFS image when the device already contains one, otherwise
24/// format a fresh BlkFS.  More explicit modes let labs and kernel syscalls
25/// distinguish "only mount an already-formatted image" from "format this device
26/// now".
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum BlkFsMountMode {
29    /// Open an existing BlkFS, or create one only when the device is blank.
30    OpenOrCreate,
31    /// Open only; return an error instead of formatting an unrecognized device.
32    OpenOnly,
33    /// Always format a new BlkFS before mounting.
34    Format,
35}
36
37/// Options for mounting an AhRightOS-native BlkFS instance.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct BlkFsMountOptions {
40    /// Policy used to interpret or initialize the target block device.
41    pub mode: BlkFsMountMode,
42}
43
44impl BlkFsMountOptions {
45    pub const fn open_or_create() -> Self {
46        Self {
47            mode: BlkFsMountMode::OpenOrCreate,
48        }
49    }
50
51    pub const fn open_only() -> Self {
52        Self {
53            mode: BlkFsMountMode::OpenOnly,
54        }
55    }
56
57    pub const fn format() -> Self {
58        Self {
59            mode: BlkFsMountMode::Format,
60        }
61    }
62}
63
64impl Default for BlkFsMountOptions {
65    fn default() -> Self {
66        Self::open_or_create()
67    }
68}
69
70/// 挂载点 — 将一个文件系统挂载到指定路径
71pub struct MountPoint {
72    /// 挂载路径 (如 "/mnt")
73    pub path: String,
74    /// 挂载的文件系统类型标识
75    pub fs_type: FsType,
76    /// BlkFS 实例 (如果是块设备文件系统)
77    pub blkfs: Option<Arc<BlkFS>>,
78    /// VirtualFS 实例 (如果是 procfs/sysfs/devtmpfs 等伪文件系统)
79    pub virtualfs: Option<Arc<dyn VirtualFileSystem>>,
80}
81
82/// 文件系统类型
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub enum FsType {
85    RamFS,
86    BlkFS,
87    ProcFS,
88    SysFS,
89    DevTmpFS,
90}
91
92impl FsType {
93    fn matches_virtualfs_name(self, name: &str) -> bool {
94        matches!(
95            (self, name),
96            (FsType::ProcFS, "procfs") | (FsType::SysFS, "sysfs") | (FsType::DevTmpFS, "devtmpfs")
97        )
98    }
99}
100
101/// 文件系统管理器
102///
103/// 管理全局文件系统实例和挂载表
104pub struct FileSystemManager {
105    /// 根目录 (RamFS)
106    pub root: Arc<Mutex<RamInode>>,
107    /// RamFS实例
108    pub ramfs: Arc<RamFS>,
109    /// 挂载表
110    pub mounts: Vec<MountPoint>,
111}
112
113impl FileSystemManager {
114    /// 创建新的文件系统管理器
115    pub fn new(ramfs: Arc<RamFS>) -> Self {
116        let root = ramfs.root();
117        FileSystemManager {
118            root,
119            ramfs,
120            mounts: Vec::new(),
121        }
122    }
123
124    /// 获取根目录
125    pub fn root(&self) -> Arc<Mutex<RamInode>> {
126        self.root.clone()
127    }
128
129    /// 获取RamFS实例
130    pub fn ramfs(&self) -> Arc<RamFS> {
131        self.ramfs.clone()
132    }
133
134    fn ensure_ramfs_directory(&self, name: &str) -> Result<bool, &'static str> {
135        if name.is_empty() || name.contains('/') {
136            return Err("Invalid directory name");
137        }
138
139        match self.ramfs.lookup(self.root.clone(), name) {
140            Ok(inode) => {
141                if inode.lock().file_type() == FileType::Directory {
142                    Ok(false)
143                } else {
144                    Err("Path exists but is not a directory")
145                }
146            }
147            Err(FileError::NotFound) => self
148                .ramfs
149                .create_directory(self.root.clone(), String::from(name))
150                .map(|_| true)
151                .map_err(|_| "Failed to create directory"),
152            Err(_) => Err("Failed to inspect directory"),
153        }
154    }
155
156    fn rollback_created_ramfs_directory(&self, name: &str, created: bool) {
157        if created {
158            let _ = self.ramfs.remove(self.root.clone(), name);
159        }
160    }
161
162    fn normalize_mount_path(path: &str) -> Result<(String, String), &'static str> {
163        let trimmed = path.trim();
164        if !trimmed.starts_with('/') {
165            return Err("Mount path must be absolute");
166        }
167
168        let dir_name = trimmed.trim_matches('/');
169        if dir_name.is_empty() {
170            return Err("Cannot mount over root");
171        }
172        if dir_name.contains('/') {
173            return Err("Nested mount paths are not supported");
174        }
175
176        let mut mount_path = String::from("/");
177        mount_path.push_str(dir_name);
178        Ok((mount_path, String::from(dir_name)))
179    }
180
181    /// 挂载一个块设备文件系统(兼容旧接口)
182    ///
183    /// # 参数
184    /// - `path`: 挂载路径(在RamFS中创建目录作为挂载点)
185    /// - `dev`: 块设备句柄
186    ///
187    /// 先尝试打开已有文件系统;如果设备未格式化,则创建新文件系统。
188    pub fn mount_blkfs(&mut self, path: &str, dev: BlockDeviceHandle) -> Result<(), &'static str> {
189        self.mount_blkfs_with_options(path, dev, BlkFsMountOptions::default())
190    }
191
192    /// 按显式策略挂载一个 AhRightOS-native BlkFS。
193    ///
194    /// `OpenOnly` 适合把 QEMU `virtio-blk` 镜像当作“真实磁盘镜像”挂载:
195    /// 如果镜像不是 BlkFS,内核会清晰失败而不会误格式化。`Format` 必须由
196    /// 调用者显式指定,用于实验中的重新格式化场景。
197    pub fn mount_blkfs_with_options(
198        &mut self,
199        path: &str,
200        dev: BlockDeviceHandle,
201        options: BlkFsMountOptions,
202    ) -> Result<(), &'static str> {
203        let (mount_path, dir_name) = Self::normalize_mount_path(path)?;
204        if self.mounts.iter().any(|m| m.path == mount_path) {
205            return Err("Mount point already exists");
206        }
207
208        let created_mount_dir = self.ensure_ramfs_directory(&dir_name)?;
209
210        let format =
211            match detect_disk_format(&dev).map_err(|_| "Failed to inspect block device format") {
212                Ok(format) => format,
213                Err(err) => {
214                    self.rollback_created_ramfs_directory(&dir_name, created_mount_dir);
215                    return Err(err);
216                }
217            };
218        let blkfs_result = match options.mode {
219            BlkFsMountMode::OpenOrCreate => match format {
220                DiskFormat::BlkFS => BlkFS::open(dev).map_err(|_| "Failed to open BlkFS"),
221                DiskFormat::Blank => BlkFS::create(dev).map_err(|_| "Failed to create BlkFS"),
222                other => Err(unsupported_disk_format_error(other)),
223            },
224            BlkFsMountMode::OpenOnly => match format {
225                DiskFormat::BlkFS => BlkFS::open(dev).map_err(|_| "Failed to open BlkFS"),
226                other => Err(unsupported_disk_format_error(other)),
227            },
228            BlkFsMountMode::Format => BlkFS::create(dev).map_err(|_| "Failed to create BlkFS"),
229        };
230        let blkfs = match blkfs_result {
231            Ok(blkfs) => Arc::new(blkfs),
232            Err(err) => {
233                self.rollback_created_ramfs_directory(&dir_name, created_mount_dir);
234                return Err(err);
235            }
236        };
237
238        self.mounts.push(MountPoint {
239            path: mount_path,
240            fs_type: FsType::BlkFS,
241            blkfs: Some(blkfs),
242            virtualfs: None,
243        });
244
245        Ok(())
246    }
247
248    /// 挂载一个虚拟文件系统(如 procfs/sysfs/devtmpfs)。
249    pub fn mount_virtualfs(
250        &mut self,
251        path: &str,
252        fs_type: FsType,
253        virtualfs: Arc<dyn VirtualFileSystem>,
254    ) -> Result<(), &'static str> {
255        let (mount_path, dir_name) = Self::normalize_mount_path(path)?;
256        if !matches!(fs_type, FsType::ProcFS | FsType::SysFS | FsType::DevTmpFS) {
257            return Err("Invalid virtual filesystem type");
258        }
259        if !fs_type.matches_virtualfs_name(virtualfs.name()) {
260            return Err("Virtual filesystem type mismatch");
261        }
262        if self.mounts.iter().any(|m| m.path == mount_path) {
263            return Err("Mount point already exists");
264        }
265
266        self.ensure_ramfs_directory(&dir_name)?;
267        self.mounts.push(MountPoint {
268            path: mount_path,
269            fs_type,
270            blkfs: None,
271            virtualfs: Some(virtualfs),
272        });
273
274        Ok(())
275    }
276
277    fn ensure_virtualfs_mounted(
278        &mut self,
279        path: &str,
280        fs_type: FsType,
281        virtualfs: Arc<dyn VirtualFileSystem>,
282    ) -> Result<(), &'static str> {
283        let (mount_path, _) = Self::normalize_mount_path(path)?;
284        if self.mounts.iter().any(|m| m.path == mount_path) {
285            return Ok(());
286        }
287        self.mount_virtualfs(path, fs_type, virtualfs)
288    }
289
290    /// 获取指定路径的BlkFS(如果已挂载)
291    pub fn get_blkfs(&self, path: &str) -> Option<Arc<BlkFS>> {
292        self.mounts
293            .iter()
294            .find(|m| m.path == path && m.fs_type == FsType::BlkFS)
295            .and_then(|m| m.blkfs.clone())
296    }
297
298    /// 卸载文件系统
299    pub fn umount(&mut self, path: &str) -> Result<(), &'static str> {
300        let (mount_path, _) = Self::normalize_mount_path(path)?;
301        let idx = self
302            .mounts
303            .iter()
304            .position(|m| m.path == mount_path)
305            .ok_or("Mount point not found")?;
306        if let Some(blkfs) = self.mounts[idx].blkfs.as_ref() {
307            blkfs
308                .sync()
309                .map_err(|_| "Failed to flush mounted filesystem")?;
310        }
311        self.mounts.remove(idx);
312        Ok(())
313    }
314}
315
316fn unsupported_disk_format_error(format: DiskFormat) -> &'static str {
317    match format {
318        DiskFormat::Blank => "Device is blank (not BlkFS)",
319        DiskFormat::BlkFS => "Failed to open BlkFS",
320        DiskFormat::InvalidBlkFS => "Invalid BlkFS superblock",
321        DiskFormat::TooSmall => "Device is too small for BlkFS",
322        DiskFormat::MasterBootRecord => "Unsupported MBR partition table",
323        DiskFormat::GuidPartitionTable => "Unsupported GPT partition table",
324        DiskFormat::FatFamily => "Unsupported FAT filesystem",
325        DiskFormat::ExtFamily => "Unsupported ext-family filesystem",
326        DiskFormat::Unknown => "Unsupported or unknown disk format",
327    }
328}
329
330lazy_static! {
331    /// 全局文件系统管理器
332    ///
333    /// 在系统启动时初始化,支持RamFS + 可选的BlkFS挂载
334    pub static ref FS_MANAGER: Mutex<FileSystemManager> = {
335        let ramfs = Arc::new(RamFS::new());
336        let manager = FileSystemManager::new(ramfs);
337        Mutex::new(manager)
338    };
339}
340
341/// 初始化文件系统
342///
343/// 创建基础目录结构
344pub fn init_filesystem() {
345    let mut manager = FS_MANAGER.lock();
346    for dir in BASE_DIRS {
347        manager
348            .ensure_ramfs_directory(dir)
349            .expect("Failed to initialize base directory");
350    }
351    manager
352        .ensure_virtualfs_mounted("/proc", FsType::ProcFS, default_procfs())
353        .expect("Failed to mount procfs");
354    manager
355        .ensure_virtualfs_mounted("/sys", FsType::SysFS, default_sysfs())
356        .expect("Failed to mount sysfs");
357    manager
358        .ensure_virtualfs_mounted("/dev", FsType::DevTmpFS, default_devtmpfs())
359        .expect("Failed to mount devtmpfs");
360}