xref: /DragonOS/kernel/src/filesystem/vfs/core.rs (revision 6d345b774223b0daaf0ee629c7fb595a1912a9e2)
1 use core::{
2     hint::spin_loop,
3     ptr::null_mut,
4     sync::atomic::{AtomicUsize, Ordering},
5 };
6 
7 use alloc::{boxed::Box, format, string::ToString, sync::Arc};
8 
9 use crate::{
10     arch::asm::current::current_pcb,
11     driver::disk::ahci::{self},
12     filesystem::{
13         devfs::DevFS,
14         fat::fs::FATFileSystem,
15         procfs::ProcFS,
16         ramfs::RamFS,
17         vfs::{file::File, mount::MountFS, FileSystem, FileType},
18     },
19     include::bindings::bindings::PAGE_4K_SIZE,
20     io::SeekFrom,
21     kerror, kinfo,
22     syscall::SystemError,
23 };
24 
25 use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId};
26 
27 /// @brief 原子地生成新的Inode号。
28 /// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的
29 /// 特殊的两个inode号:
30 /// [0]: 对应'.'目录项
31 /// [1]: 对应'..'目录项
32 pub fn generate_inode_id() -> InodeId {
33     static INO: AtomicUsize = AtomicUsize::new(1);
34     return INO.fetch_add(1, Ordering::SeqCst);
35 }
36 
37 static mut __ROOT_INODE: *mut Arc<dyn IndexNode> = null_mut();
38 
39 /// @brief 获取全局的根节点
40 #[inline(always)]
41 #[allow(non_snake_case)]
42 pub fn ROOT_INODE() -> Arc<dyn IndexNode> {
43     unsafe {
44         return __ROOT_INODE.as_ref().unwrap().clone();
45     }
46 }
47 
48 #[no_mangle]
49 pub extern "C" fn vfs_init() -> i32 {
50     // 使用Ramfs作为默认的根文件系统
51     let ramfs = RamFS::new();
52     let mount_fs = MountFS::new(ramfs, None);
53     let root_inode = Box::leak(Box::new(mount_fs.root_inode()));
54 
55     unsafe {
56         __ROOT_INODE = root_inode;
57     }
58 
59     // 创建文件夹
60     root_inode
61         .create("proc", FileType::Dir, 0o777)
62         .expect("Failed to create /proc");
63     root_inode
64         .create("dev", FileType::Dir, 0o777)
65         .expect("Failed to create /dev");
66 
67     // // 创建procfs实例
68     let procfs: Arc<ProcFS> = ProcFS::new();
69 
70     // procfs挂载
71     let _t = root_inode
72         .find("proc")
73         .expect("Cannot find /proc")
74         .mount(procfs)
75         .expect("Failed to mount procfs.");
76     kinfo!("ProcFS mounted.");
77 
78     // 创建 devfs 实例
79     let devfs: Arc<DevFS> = DevFS::new();
80     // devfs 挂载
81     let _t = root_inode
82         .find("dev")
83         .expect("Cannot find /dev")
84         .mount(devfs)
85         .expect("Failed to mount devfs");
86     kinfo!("DevFS mounted.");
87 
88     let root_inode = ROOT_INODE().list().expect("VFS init failed");
89     if root_inode.len() > 0 {
90         kinfo!("Successfully initialized VFS!");
91     }
92     return 0;
93 }
94 
95 /// @brief 真正执行伪文件系统迁移的过程
96 ///
97 /// @param mountpoint_name 在根目录下的挂载点的名称
98 /// @param inode 原本的挂载点的inode
99 fn do_migrate(
100     new_root_inode: Arc<dyn IndexNode>,
101     mountpoint_name: &str,
102     fs: &MountFS,
103 ) -> Result<(), SystemError> {
104     let r = new_root_inode.find(mountpoint_name);
105     let mountpoint = if r.is_err() {
106         new_root_inode
107             .create(mountpoint_name, FileType::Dir, 0o777)
108             .expect(format!("Failed to create '/{mountpoint_name}'").as_str())
109     } else {
110         r.unwrap()
111     };
112     // 迁移挂载点
113     mountpoint
114         .mount(fs.inner_filesystem())
115         .expect(format!("Failed to migrate {mountpoint_name}").as_str());
116     return Ok(());
117 }
118 
119 /// @brief 迁移伪文件系统的inode
120 /// 请注意,为了避免删掉了伪文件系统内的信息,因此没有在原root inode那里调用unlink.
121 fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemError> {
122     kinfo!("VFS: Migrating filesystems...");
123 
124     // ==== 在这里获取要被迁移的文件系统的inode ===
125     let binding = ROOT_INODE().find("proc").expect("ProcFS not mounted!").fs();
126     let proc: &MountFS = binding.as_any_ref().downcast_ref::<MountFS>().unwrap();
127     let binding = ROOT_INODE().find("dev").expect("DevFS not mounted!").fs();
128     let dev: &MountFS = binding.as_any_ref().downcast_ref::<MountFS>().unwrap();
129 
130     let new_fs = MountFS::new(new_fs, None);
131     // 获取新的根文件系统的根节点的引用
132     let new_root_inode = Box::leak(Box::new(new_fs.root_inode()));
133 
134     // 把上述文件系统,迁移到新的文件系统下
135     do_migrate(new_root_inode.clone(), "proc", proc)?;
136     do_migrate(new_root_inode.clone(), "dev", dev)?;
137 
138     unsafe {
139         // drop旧的Root inode
140         let old_root_inode: Box<Arc<dyn IndexNode>> = Box::from_raw(__ROOT_INODE);
141         __ROOT_INODE = null_mut();
142         drop(old_root_inode);
143 
144         // 设置全局的新的ROOT Inode
145         __ROOT_INODE = new_root_inode;
146     }
147 
148     kinfo!("VFS: Migrate filesystems done!");
149 
150     return Ok(());
151 }
152 
153 #[no_mangle]
154 pub extern "C" fn mount_root_fs() -> i32 {
155     kinfo!("Try to mount FAT32 as root fs...");
156     let partiton: Arc<crate::io::disk_info::Partition> =
157         ahci::get_disks_by_name("ahci_disk_0".to_string())
158             .unwrap()
159             .0
160             .lock()
161             .partitions[0]
162             .clone();
163 
164     let fatfs: Result<Arc<FATFileSystem>, SystemError> = FATFileSystem::new(partiton);
165     if fatfs.is_err() {
166         kerror!(
167             "Failed to initialize fatfs, code={:?}",
168             fatfs.as_ref().err()
169         );
170         loop {
171             spin_loop();
172         }
173     }
174     let fatfs: Arc<FATFileSystem> = fatfs.unwrap();
175     let r = migrate_virtual_filesystem(fatfs);
176     if r.is_err() {
177         kerror!("Failed to migrate virtual filesystem to FAT32!");
178         loop {
179             spin_loop();
180         }
181     }
182     kinfo!("Successfully migrate rootfs to FAT32!");
183 
184     return 0;
185 }
186 
187 /// @brief 为当前进程打开一个文件
188 pub fn do_open(path: &str, mode: FileMode) -> Result<i32, SystemError> {
189     // 文件名过长
190     if path.len() > PAGE_4K_SIZE as usize {
191         return Err(SystemError::ENAMETOOLONG);
192     }
193 
194     let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
195 
196     let inode: Arc<dyn IndexNode> = if inode.is_err() {
197         let errno = inode.unwrap_err();
198         // 文件不存在,且需要创建
199         if mode.contains(FileMode::O_CREAT)
200             && !mode.contains(FileMode::O_DIRECTORY)
201             && errno == SystemError::ENOENT
202         {
203             let (filename, parent_path) = rsplit_path(path);
204             // 查找父目录
205             let parent_inode: Arc<dyn IndexNode> =
206                 ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
207             // 创建文件
208             let inode: Arc<dyn IndexNode> = parent_inode.create(filename, FileType::File, 0o777)?;
209             inode
210         } else {
211             // 不需要创建文件,因此返回错误码
212             return Err(errno);
213         }
214     } else {
215         inode.unwrap()
216     };
217 
218     let file_type: FileType = inode.metadata()?.file_type;
219     // 如果要打开的是文件夹,而目标不是文件夹
220     if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
221         return Err(SystemError::ENOTDIR);
222     }
223 
224     // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
225     if mode.contains(FileMode::O_TRUNC)
226         && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY))
227         && file_type == FileType::File
228     {
229         inode.truncate(0)?;
230     }
231 
232     // 创建文件对象
233     let mut file: File = File::new(inode, mode)?;
234 
235     // 打开模式为“追加”
236     if mode.contains(FileMode::O_APPEND) {
237         file.lseek(SeekFrom::SeekEnd(0))?;
238     }
239 
240     // 把文件对象存入pcb
241     return current_pcb().alloc_fd(file, None);
242 }
243 
244 /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
245 ///
246 /// @param fd 文件描述符编号
247 /// @param buf 输出缓冲区。
248 ///
249 /// @return Ok(usize) 成功读取的数据的字节数
250 /// @return Err(SystemError) 读取失败,返回posix错误码
251 pub fn do_read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
252     let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
253     if file.is_none() {
254         return Err(SystemError::EBADF);
255     }
256     let file: &mut File = file.unwrap();
257 
258     return file.read(buf.len(), buf);
259 }
260 
261 /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
262 ///
263 /// @param fd 文件描述符编号
264 /// @param buf 输入缓冲区。
265 ///
266 /// @return Ok(usize) 成功写入的数据的字节数
267 /// @return Err(SystemError) 写入失败,返回posix错误码
268 pub fn do_write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
269     let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
270     if file.is_none() {
271         return Err(SystemError::EBADF);
272     }
273     let file: &mut File = file.unwrap();
274 
275     return file.write(buf.len(), buf);
276 }
277 
278 /// @brief 调整文件操作指针的位置
279 ///
280 /// @param fd 文件描述符编号
281 /// @param seek 调整的方式
282 ///
283 /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
284 /// @return Err(SystemError) 调整失败,返回posix错误码
285 pub fn do_lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
286     let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
287     if file.is_none() {
288         return Err(SystemError::EBADF);
289     }
290     let file: &mut File = file.unwrap();
291     return file.lseek(seek);
292 }
293 
294 /// @brief 创建文件/文件夹
295 pub fn do_mkdir(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
296     // 文件名过长
297     if path.len() > PAGE_4K_SIZE as usize {
298         return Err(SystemError::ENAMETOOLONG);
299     }
300 
301     let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
302 
303     if inode.is_err() {
304         let errno = inode.unwrap_err();
305         // 文件不存在,且需要创建
306         if errno == SystemError::ENOENT {
307             let (filename, parent_path) = rsplit_path(path);
308             // 查找父目录
309             let parent_inode: Arc<dyn IndexNode> =
310                 ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
311             // 创建文件夹
312             let _create_inode: Arc<dyn IndexNode> =
313                 parent_inode.create(filename, FileType::Dir, 0o777)?;
314         } else {
315             // 不需要创建文件,因此返回错误码
316             return Err(errno);
317         }
318     }
319 
320     return Ok(0);
321 }
322 
323 /// @breif 删除文件夹
324 pub fn do_remove_dir(path: &str) -> Result<u64, SystemError> {
325     // 文件名过长
326     if path.len() > PAGE_4K_SIZE as usize {
327         return Err(SystemError::ENAMETOOLONG);
328     }
329 
330     let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
331 
332     if inode.is_err() {
333         let errno = inode.unwrap_err();
334         // 文件不存在
335         if errno == SystemError::ENOENT {
336             return Err(SystemError::ENOENT);
337         }
338     }
339 
340     let (filename, parent_path) = rsplit_path(path);
341     // 查找父目录
342     let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
343 
344     if parent_inode.metadata()?.file_type != FileType::Dir {
345         return Err(SystemError::ENOTDIR);
346     }
347 
348     let target_inode: Arc<dyn IndexNode> = parent_inode.find(filename)?;
349     if target_inode.metadata()?.file_type != FileType::Dir {
350         return Err(SystemError::ENOTDIR);
351     }
352 
353     // 删除文件夹
354     parent_inode.rmdir(filename)?;
355 
356     return Ok(0);
357 }
358 
359 /// @brief 删除文件
360 pub fn do_unlink_at(path: &str, _mode: FileMode) -> Result<u64, SystemError> {
361     // 文件名过长
362     if path.len() > PAGE_4K_SIZE as usize {
363         return Err(SystemError::ENAMETOOLONG);
364     }
365 
366     let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
367 
368     if inode.is_err() {
369         let errno = inode.clone().unwrap_err();
370         // 文件不存在,且需要创建
371         if errno == SystemError::ENOENT {
372             return Err(SystemError::ENOENT);
373         }
374     }
375     // 禁止在目录上unlink
376     if inode.unwrap().metadata()?.file_type == FileType::Dir {
377         return Err(SystemError::EPERM);
378     }
379 
380     let (filename, parent_path) = rsplit_path(path);
381     // 查找父目录
382     let parent_inode: Arc<dyn IndexNode> = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
383 
384     if parent_inode.metadata()?.file_type != FileType::Dir {
385         return Err(SystemError::ENOTDIR);
386     }
387 
388     // 删除文件
389     parent_inode.unlink(filename)?;
390 
391     return Ok(0);
392 }
393