From 07816d4df5a431c193c251fc1ccf988dd8624faa Mon Sep 17 00:00:00 2001 From: pierrecashon <2938806204@qq.com> Date: Mon, 24 Mar 2025 16:32:42 +0800 Subject: [PATCH 1/2] add mount,umount,fstat,openat --- easy-fs/src/efs.rs | 6 +++ easy-fs/src/vfs.rs | 23 +++++++++ ext4-test-fuse/src/main.rs | 11 ++++ ext4/src/dentry.rs | 1 + ext4/src/fs.rs | 21 +++++++- ext4/src/inode.rs | 41 ++++++++++++++- os/Makefile | 3 ++ os/src/fs/inode.rs | 11 ++++ os/src/main.rs | 2 +- os/src/syscall/fs.rs | 91 +++++++++++++++++++++++++++++++--- os/src/syscall/mod.rs | 23 +++++++-- user/src/lib.rs | 2 +- vfs-defs/src/file.rs | 4 +- vfs-defs/src/filesystemtype.rs | 18 +++++++ vfs-defs/src/inode.rs | 5 ++ vfs-defs/src/lib.rs | 46 ++++++++++++++++- 16 files changed, 289 insertions(+), 19 deletions(-) diff --git a/easy-fs/src/efs.rs b/easy-fs/src/efs.rs index 4482421..c7ef431 100644 --- a/easy-fs/src/efs.rs +++ b/easy-fs/src/efs.rs @@ -192,6 +192,12 @@ impl FileSystemType for EfsFsType{ Ok(root_dentry) } + fn umount(self:Arc<Self>, + path:&str, + _flags:MountFlags + )->SysResult<()> { + Ok(()) + } } /// diff --git a/easy-fs/src/vfs.rs b/easy-fs/src/vfs.rs index 4c4dd5a..d7ff161 100644 --- a/easy-fs/src/vfs.rs +++ b/easy-fs/src/vfs.rs @@ -37,6 +37,29 @@ impl Inode for EfsInode{ fn get_meta(&self) -> &InodeMeta { &self.meta } + fn get_attr(&self)->SysResult<vfs_defs::Kstat> { + Ok(vfs_defs::Kstat{ + st_dev: 0, + st_ino: 0, + st_mode: 0, + st_nlink: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + __pad: 0, + st_size: 0, + st_blksize: 0, + __pad2: 0, + st_blocks: 0, + st_atime_sec: 0, + st_atime_nsec: 0, + st_mtime_sec: 0, + st_mtime_nsec: 0, + st_ctime_sec: 0, + st_ctime_nsec: 0, + unused: 0, + }) + } /// Clear the data in current inode fn clear(&self) { let (mut inner,mut meta) = self.lock_inner(); diff --git a/ext4-test-fuse/src/main.rs b/ext4-test-fuse/src/main.rs index b77a665..6d68118 100644 --- a/ext4-test-fuse/src/main.rs +++ b/ext4-test-fuse/src/main.rs @@ -100,6 +100,17 @@ fn easy_fs_pack() -> std::io::Result<()> { name_with_ext }) .collect(); + + { let mnt = root_dentry.create("mnt",DiskInodeType::Directory).unwrap(); + let mut host_file = File::open(format!("{}{}", src_path, "mnt/test_mount")).unwrap(); + let mut all_data: Vec<u8> = Vec::new(); + host_file.read_to_end(&mut all_data).unwrap(); + // create a file in ext4 + let den =mnt.create("test_mount",DiskInodeType::File).unwrap(); + let inode = den.get_inode().unwrap().get_meta().ino; + // write data to ext4 + sb.ext4fs.ext4_file_write(inode as u64, 0, all_data.as_slice()); + } for app in apps { // load app data from host file system println!("{}",app); diff --git a/ext4/src/dentry.rs b/ext4/src/dentry.rs index 3f4c4f6..8abeb38 100644 --- a/ext4/src/dentry.rs +++ b/ext4/src/dentry.rs @@ -42,6 +42,7 @@ impl Dentry for Ext4Dentry{ } } let child_inode = Ext4Inode::new(InodeMeta::new(child_ino.unwrap() as usize, sblock),); + child_inode.set_type(_type); child_dir.set_inode(Arc::new(child_inode)); Ok(child_dir) } diff --git a/ext4/src/fs.rs b/ext4/src/fs.rs index 2714a64..6b5e6ad 100644 --- a/ext4/src/fs.rs +++ b/ext4/src/fs.rs @@ -4,7 +4,7 @@ use system_result::SysResult; use device::BlockDevice; use crate::{dentry::Ext4Dentry, superblock::Ext4Superblock, Ext4Inode}; use alloc::string::{String,ToString}; - +const MODULE_LEVEL:log::Level = log::Level::Trace; pub struct Ext4ImplFsType{ inner:FileSystemTypeInner } @@ -33,15 +33,32 @@ impl FileSystemType for Ext4ImplFsType{ let root_inode = Arc::new(Ext4Inode::new(InodeMeta::new(root_ino, superblock.clone()))); root_inode.set_type(vfs_defs::DiskInodeType::Directory); let root_dentry; + let abs_mount_path; + let mut path = String::new(); if parent.is_none(){ root_dentry = Arc::new(Ext4Dentry::new(DentryInner::new(name.to_string(), superblock.clone(),None))); + abs_mount_path = "/"; } else{ + path = parent.as_ref().unwrap().path()+name; + abs_mount_path = path.as_str(); root_dentry = Arc::new(Ext4Dentry::new(DentryInner::new(name.to_string(), superblock.clone(),Some(Arc::downgrade(&parent.unwrap()))))); } + log_debug!("abs_m_path:{}",abs_mount_path); root_dentry.set_inode(root_inode); superblock.set_root_dentry(root_dentry.clone()); - self.add_superblock("/", superblock); + self.add_superblock(&abs_mount_path, superblock); Ok(root_dentry) } + fn umount(self:Arc<Self>, + path:&str, + _flags:vfs_defs::MountFlags + )->SysResult<()> { + let r = self.remove_superblock(path); + log_debug!("umount_path:{}",path); + if let Err(e) = r{ + return Err(e); + } + Ok(()) + } } \ No newline at end of file diff --git a/ext4/src/inode.rs b/ext4/src/inode.rs index a5e37d2..63bbff4 100644 --- a/ext4/src/inode.rs +++ b/ext4/src/inode.rs @@ -1,6 +1,9 @@ -use vfs_defs::{Inode,InodeMeta}; +use ext4_rs::Ext4Error; +use vfs_defs::{Inode,InodeMeta, Kstat}; use super::Ext4Superblock; use system_result::SysError; +use ext4_rs::Errno; +const MODULE_LEVEL:log::Level = log::Level::Trace; pub struct Ext4Inode{ meta:InodeMeta, } @@ -18,6 +21,42 @@ impl Inode for Ext4Inode{ fn get_meta(&self) -> &InodeMeta { &self.meta } + fn get_attr(&self)->system_result::SysResult<Kstat> { + let sb = self.get_meta().superblock.upgrade().unwrap().downcast_arc::<Ext4Superblock>().map_err(|_| SysError::ENOENT)?; + let r = sb.ext4fs.fuse_getattr(self.get_meta().ino as u64); + if let Err(e) = r{ + let err = match e.error(){ + Errno::ENOENT=>SysError::ENOENT, + _ => SysError::EINVAL, + }; + Err(err) + } + else{ + let attr = r.unwrap(); + Ok(Kstat{ + st_dev: 0, + st_ino: attr.ino, + st_mode: 0, + st_nlink: attr.nlink, + st_uid: attr.uid, + st_gid: attr.gid, + st_rdev: attr.rdev as u64, + __pad: 0, + st_size: attr.size, + st_blksize: attr.blksize, + __pad2: 0, + st_blocks: attr.blocks, + st_atime_sec: attr.atime as u64, + st_atime_nsec: attr.atime as u64, + st_mtime_sec: attr.mtime as u64, + st_mtime_nsec: attr.mtime as u64, + st_ctime_sec: attr.ctime as u64, + st_ctime_nsec: attr.ctime as u64, + unused: 0, + }) + } + + } fn load_from_disk(&self) { } diff --git a/os/Makefile b/os/Makefile index 75f671a..6a3c8d9 100644 --- a/os/Makefile +++ b/os/Makefile @@ -161,6 +161,9 @@ debug: build gdbserver: build @$(QEMU_EXEC) -s -S +test-gdbserver: testbuild + @$(QEMU_EXEC) -s -S + gdbclient: @riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234' diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs index 4d789f5..cd8c201 100644 --- a/os/src/fs/inode.rs +++ b/os/src/fs/inode.rs @@ -197,6 +197,17 @@ fn path_to_dirent_(path:&str, } while let Some(new_path) = skipelem(current,name){ current = new_path; + if name == "."{ + continue; + } + if name == ".."{ + if let Some(father) = dentry.get_father(){ + dentry = father; + continue; + }else{ + return None; + } + } if to_father && current.len() == 0 { return Some(dentry); } diff --git a/os/src/main.rs b/os/src/main.rs index 29874bd..91dceb2 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -116,7 +116,7 @@ impl ArchInterface for ArchInterfaceImpl { let args = ctx.args(); // get system call return value // info!("syscall: {}", ctx[TrapFrameArgs::SYSCALL]); - let result = syscall(ctx[TrapFrameArgs::SYSCALL], [args[0], args[1], args[2]]); + let result = syscall(ctx[TrapFrameArgs::SYSCALL], [args[0], args[1], args[2],args[3],args[4]]); // cx is changed during sys_exec, so we have to call it again ctx[TrapFrameArgs::RET] = result as usize; } diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 9bed6de..6f3c863 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -1,9 +1,16 @@ //! File and filesystem-related syscalls use crate::fs::open_file; use crate::fs::make_pipe; +use crate::fs::path_to_dentry; +use crate::fs::path_to_father_dentry; use crate::mm::{translated_refmut,translated_byte_buffer, translated_str}; use crate::task::{current_task, current_user_token}; +use device::BLOCK_DEVICE; +use vfs_defs::Kstat; +use vfs_defs::MountFlags; use vfs_defs::{OpenFlags,UserBuffer}; +use vfs::FILE_SYSTEMS; +use alloc::string::String; // use crate::config::PAGE_SIZE; use crate::mm::frame_alloc_more; @@ -18,6 +25,7 @@ use alloc::sync::Arc; use alloc::vec::Vec; // //const HEAP_MAX: usize = 0; +pub const AT_FDCWD: isize = -100; pub fn sys_write(fd: usize, buf: *mut u8, len: usize) -> isize { let token = current_user_token(); @@ -59,18 +67,35 @@ pub fn sys_read(fd: usize, buf: *mut u8, len: usize) -> isize { } } -pub fn sys_open(path: *const u8, flags: u32) -> isize { +pub fn sys_openat(pfd:isize,path: *const u8, flags: u32,_mode:u32) -> isize { let task = current_task().unwrap(); let token = current_user_token(); let path = translated_str(token, path); - if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) { - let mut inner = task.inner_exclusive_access(); - let fd = inner.alloc_fd(); - inner.fd_table[fd] = Some(inode); - fd as isize - } else { - -1 + if path.chars().next() == Some('/') || pfd == AT_FDCWD{ + if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) { + let mut inner = task.inner_exclusive_access(); + let fd = inner.alloc_fd(); + inner.fd_table[fd] = Some(inode); + return fd as isize; + } else { + return -1; + } + } + let mut inner = task.inner_exclusive_access(); + if let Some(file) = &inner.fd_table[pfd as usize]{ + let father_path = file.get_dentry().path(); + let child_path = father_path+&path; + if let Some(inode) = open_file(child_path.as_str(), OpenFlags::from_bits(flags).unwrap()) { + let fd = inner.alloc_fd(); + inner.fd_table[fd] = Some(inode); + return fd as isize; + } else { + return -1; + } + } + return -1; + } pub fn sys_close(fd: usize) -> isize { @@ -195,4 +220,54 @@ pub fn sys_brk(mut new_brk: usize) -> isize { 0 } +} + +pub fn sys_mount(_special:*const u8,dir:*const u8,fstype:*const u8,_flags:u32,_data:*const u8)->isize{ + let token = current_user_token(); + let dir = translated_str(token, dir); + let fstype = translated_str(token, fstype); + let ext4fstype = FILE_SYSTEMS.lock().find_fs(&String::from("Ext4")).unwrap(); + if fstype == "vfat"{ + let mut name = String::new(); + let parent = path_to_father_dentry(dir.as_str(), &mut name); + let device = BLOCK_DEVICE.get().unwrap().clone(); + let r = ext4fstype.mount(name.as_str(), parent, MountFlags::empty(), Some(device)); + if r.is_err(){ + return -1; + } + return 0; + } + else{ + return -1; + } +} + +pub fn sys_umount(special:*const u8,_flags:u32)->isize{ + let token = current_user_token(); + let path = translated_str(token, special); + let ext4fstype = FILE_SYSTEMS.lock().find_fs(&String::from("Ext4")).unwrap(); + if let Some(dentry) = path_to_dentry(&path){ + if let Err(_e) = ext4fstype.umount(dentry.path().as_str(), MountFlags::empty()){ + return -1; + } + return 0; + } + return -1; + +} + +pub fn sys_fstat(fd:usize,kst:*mut Kstat)->isize{ + let token = current_user_token(); + let task = current_task().unwrap(); + if let Some(file) = task.inner_exclusive_access().fd_table[fd].clone() { + let r = file.get_dentry().get_inode().unwrap().get_attr(); + if r.is_err(){ + return -1; + } + let kst = translated_refmut(token, kst); + let attr = r.unwrap(); + *kst = attr; + return 0; + } + return -1; } \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 54c69b5..4ce9e53 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -13,11 +13,14 @@ const SYSCALL_CHDIR: usize = 9; const SYSCALL_UNLINK: usize = 18; const SYSCALL_LINK: usize = 19; const SYSCALL_MKDIR: usize = 20; -const SYSCALL_OPEN: usize = 56; +const SYSCALL_UMOUNT: usize = 39; +const SYSCALL_MOUNT: usize = 40; +const SYSCALL_OPENAT: usize = 56; const SYSCALL_CLOSE: usize = 57; const SYSCALL_PIPE: usize = 59; const SYSCALL_READ: usize = 63; const SYSCALL_WRITE: usize = 64; +const SYSCALL_FSTAT: usize = 80; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; @@ -35,7 +38,7 @@ use process::*; const MODULE_LEVEL:log::Level = log::Level::Trace; /// handle syscall exception with `syscall_id` and other arguments -pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { +pub fn syscall(syscall_id: usize, args: [usize; 5]) -> isize { // println!("syscallid:{}",syscall_id); let mut result:isize = 0; match syscall_id { @@ -55,8 +58,8 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { result = sys_mkdir(args[0] as *const u8); log_debug!("syscall_mkdir result:{}",result); } - SYSCALL_OPEN => { - result = sys_open(args[0] as *const u8, args[1] as u32); + SYSCALL_OPENAT => { + result = sys_openat(args[0] as isize,args[1] as *const u8, args[2] as u32,args[3] as u32); log_debug!("syscall_open result:{}",result); }, SYSCALL_CLOSE => { @@ -108,6 +111,18 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { result = sys_brk(args[0]); log_debug!("syscall_pipe result:{}",result); }, + SYSCALL_MOUNT => { + result = sys_mount(args[0] as *const u8,args[1] as *const u8,args[2] as *const u8,args[3] as u32,args[4] as *const u8,); + log_debug!("syscall_mount result:{}",result); + }, + SYSCALL_UMOUNT => { + result = sys_umount(args[0] as *const u8,args[1] as u32); + log_debug!("syscall_umount result:{}",result); + }, + SYSCALL_FSTAT => { + result = sys_fstat(args[0],args[1] as *mut vfs_defs::Kstat); + log_debug!("syscall_umount result:{}",result); + }, _ => panic!("Unsupported syscall_id: {}", syscall_id), } result diff --git a/user/src/lib.rs b/user/src/lib.rs index fc926b3..5a71876 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -78,7 +78,7 @@ bitflags! { const RDONLY = 0; const WRONLY = 1 << 0; const RDWR = 1 << 1; - const CREATE = 1 << 9; + const CREATE = 1 << 6; const TRUNC = 1 << 10; } } diff --git a/vfs-defs/src/file.rs b/vfs-defs/src/file.rs index 65f9fb2..aac9504 100644 --- a/vfs-defs/src/file.rs +++ b/vfs-defs/src/file.rs @@ -15,9 +15,11 @@ bitflags! { ///Read & Write const RDWR = 1 << 1; ///Allow create - const CREATE = 1 << 9; + const CREATE = 1 << 6; ///Clear file and return an empty one const TRUNC = 1 << 10; + /// + const DIRECTORY = 1 << 16; } } impl OpenFlags { diff --git a/vfs-defs/src/filesystemtype.rs b/vfs-defs/src/filesystemtype.rs index 3ae4dc6..4bd4164 100644 --- a/vfs-defs/src/filesystemtype.rs +++ b/vfs-defs/src/filesystemtype.rs @@ -44,10 +44,28 @@ pub trait FileSystemType: Send + Sync { unimplemented!() } /// + fn umount(self:Arc<Self>, + path:&str, + _flags:MountFlags + )->SysResult<()>; + /// fn add_superblock(&self, abs_mount_path: &str, superblock: Arc<dyn SuperBlock>) { self.get_inner() .superblocks .lock() .insert(abs_mount_path.to_string(), superblock); } + /// + fn remove_superblock(&self,abs_mount_path: &str)->SysResult<()>{ + if let Some(_sb) = self.get_inner() + .superblocks + .lock() + .remove(abs_mount_path){ + Ok(()) + } + else{ + Err(SysError::ENOENT) + } + + } } diff --git a/vfs-defs/src/inode.rs b/vfs-defs/src/inode.rs index fab6781..4fae35e 100644 --- a/vfs-defs/src/inode.rs +++ b/vfs-defs/src/inode.rs @@ -1,6 +1,9 @@ use spin::{Mutex, MutexGuard}; use alloc::sync::{Weak,Arc}; use downcast_rs::{impl_downcast, DowncastSync}; +use system_result::SysResult; +use crate::Kstat; + use super::SuperBlock; /// Type of a disk inode #[derive(Clone, Copy)] @@ -74,6 +77,8 @@ pub trait Inode: Send + Sync+ DowncastSync { /// fn get_meta(&self) -> &InodeMeta; /// + fn get_attr(&self)->SysResult<Kstat>; + /// fn get_size(&self) -> u32 {//è¿™è¦æ”¹ self.get_meta().inner.lock().size } diff --git a/vfs-defs/src/lib.rs b/vfs-defs/src/lib.rs index 66300aa..ad11d7b 100644 --- a/vfs-defs/src/lib.rs +++ b/vfs-defs/src/lib.rs @@ -13,4 +13,48 @@ pub use filesystemtype::{FileSystemType,FileSystemTypeInner,MountFlags}; pub use dentry::{Dentry,DentryInner,DentryState}; pub use superblock::{SuperBlock,SuperBlockInner}; pub use inode::{Inode,InodeMeta,InodeMetaInner,DiskInodeType,InodeState}; -pub use file::{File,FileInner,OpenFlags,UserBuffer,UserBufferIterator}; \ No newline at end of file +pub use file::{File,FileInner,OpenFlags,UserBuffer,UserBufferIterator}; + +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)] +#[repr(C)] +/// +pub struct Kstat { + /// + pub st_dev: u64, + /// + pub st_ino: u64, + /// + pub st_mode: u32, + /// + pub st_nlink: u32, + /// + pub st_uid: u32, + /// + pub st_gid: u32, + /// + pub st_rdev: u64, + /// + pub __pad: u64, + /// + pub st_size: u64, + /// + pub st_blksize: u32, + /// + pub __pad2: u32, + /// + pub st_blocks: u64, + /// + pub st_atime_sec: u64, + /// + pub st_atime_nsec: u64, + /// + pub st_mtime_sec: u64, + /// + pub st_mtime_nsec: u64, + /// + pub st_ctime_sec: u64, + /// + pub st_ctime_nsec: u64, + /// + pub unused: u64, +} \ No newline at end of file -- GitLab From b028751cee7432d5a221384482b0823e79fdec21 Mon Sep 17 00:00:00 2001 From: pierrecashon <2938806204@qq.com> Date: Mon, 24 Mar 2025 20:48:36 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B6=88=E9=99=A4=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/syscall/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 6f3c863..55db4a5 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -5,12 +5,12 @@ use crate::fs::path_to_dentry; use crate::fs::path_to_father_dentry; use crate::mm::{translated_refmut,translated_byte_buffer, translated_str}; use crate::task::{current_task, current_user_token}; +use alloc::string::String; use device::BLOCK_DEVICE; use vfs_defs::Kstat; use vfs_defs::MountFlags; use vfs_defs::{OpenFlags,UserBuffer}; use vfs::FILE_SYSTEMS; -use alloc::string::String; // use crate::config::PAGE_SIZE; use crate::mm::frame_alloc_more; @@ -23,6 +23,7 @@ use crate::mm::MapType; use arch::addr::{PhysPage, VirtAddr, VirtPage}; use alloc::sync::Arc; use alloc::vec::Vec; +use core::ptr; // //const HEAP_MAX: usize = 0; pub const AT_FDCWD: isize = -100; -- GitLab