From ece1a545ce2fae4ca519451b879100d253ff3877 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Thu, 2 Mar 2023 09:36:17 +0800 Subject: [PATCH] Enhance the vnode --- .../fs/file_handle/inode_handle/dyn_cap.rs | 15 +- .../src/fs/file_handle/inode_handle/mod.rs | 45 ++--- .../fs/file_handle/inode_handle/static_cap.rs | 5 + .../libs/jinux-std/src/fs/file_handle/mod.rs | 2 +- .../libs/jinux-std/src/fs/fs_resolver.rs | 39 ++-- .../libs/jinux-std/src/fs/ramfs/fs.rs | 10 +- .../jinux-std/src/fs/utils/dentry_cache.rs | 69 ++++--- .../libs/jinux-std/src/fs/utils/inode.rs | 4 +- .../libs/jinux-std/src/fs/utils/vnode.rs | 173 +++++++++++++++++- .../libs/jinux-std/src/process/mod.rs | 4 +- .../libs/jinux-std/src/syscall/readlink.rs | 2 +- .../libs/jinux-std/src/syscall/rename.rs | 4 +- .../libs/jinux-std/src/syscall/stat.rs | 2 +- .../libs/jinux-std/src/syscall/symlink.rs | 2 +- 14 files changed, 279 insertions(+), 97 deletions(-) diff --git a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs index e131d0f4a..626c57cd7 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs @@ -9,14 +9,14 @@ impl InodeHandle { access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { - let inode_info = dentry.vnode().inode().metadata(); - if access_mode.is_readable() && !inode_info.mode.is_readable() { + let vnode = dentry.vnode(); + if access_mode.is_readable() && !vnode.inode_mode().is_readable() { return_errno_with_message!(Errno::EACCES, "File is not readable"); } - if access_mode.is_writable() && !inode_info.mode.is_writable() { + if access_mode.is_writable() && !vnode.inode_mode().is_writable() { return_errno_with_message!(Errno::EACCES, "File is not writable"); } - if access_mode.is_writable() && inode_info.type_ == InodeType::Dir { + if access_mode.is_writable() && vnode.inode_type() == InodeType::Dir { return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write"); } let inner = Arc::new(InodeHandle_ { @@ -43,6 +43,13 @@ impl InodeHandle { self.0.read(buf) } + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + if !self.1.contains(Rights::READ) { + return_errno_with_message!(Errno::EBADF, "File is not readable"); + } + self.0.read_to_end(buf) + } + pub fn write(&self, buf: &[u8]) -> Result { if !self.1.contains(Rights::WRITE) { return_errno_with_message!(Errno::EBADF, "File is not writable"); diff --git a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs index 558c74a48..61b287a3d 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs @@ -8,8 +8,6 @@ use crate::fs::utils::{ }; use crate::prelude::*; use crate::rights::Rights; -use alloc::sync::Arc; -use jinux_frame::vm::VmIo; pub struct InodeHandle(Arc, R); @@ -23,20 +21,10 @@ struct InodeHandle_ { impl InodeHandle_ { pub fn read(&self, buf: &mut [u8]) -> Result { let mut offset = self.offset.lock(); - let file_size = self.dentry.vnode().inode().metadata().size; - let start = file_size.min(*offset); - let end = file_size.min(*offset + buf.len()); let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { - self.dentry - .vnode() - .inode() - .read_at(start, &mut buf[0..end - start])? + self.dentry.vnode().read_direct_at(*offset, buf)? } else { - self.dentry - .vnode() - .pages() - .read_bytes(start, &mut buf[0..end - start])?; - end - start + self.dentry.vnode().read_at(*offset, buf)? }; *offset += len; @@ -45,29 +33,28 @@ impl InodeHandle_ { pub fn write(&self, buf: &[u8]) -> Result { let mut offset = self.offset.lock(); - let file_size = self.dentry.vnode().inode().metadata().size; if self.status_flags.lock().contains(StatusFlags::O_APPEND) { - *offset = file_size; + *offset = self.dentry.vnode().len(); } let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { - self.dentry.vnode().inode().write_at(*offset, buf)? + self.dentry.vnode().write_direct_at(*offset, buf)? } else { - let pages = self.dentry.vnode().pages(); - let should_expand_size = *offset + buf.len() > file_size; - if should_expand_size { - pages.resize(*offset + buf.len())?; - } - pages.write_bytes(*offset, buf)?; - if should_expand_size { - self.dentry.vnode().inode().resize(*offset + buf.len())?; - } - buf.len() + self.dentry.vnode().write_at(*offset, buf)? }; *offset += len; Ok(len) } + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { + self.dentry.vnode().read_direct_to_end(buf)? + } else { + self.dentry.vnode().read_to_end(buf)? + }; + Ok(len) + } + pub fn seek(&self, pos: SeekFrom) -> Result { let mut offset = self.offset.lock(); let new_offset: isize = match pos { @@ -78,7 +65,7 @@ impl InodeHandle_ { off as isize } SeekFrom::End(off /* as isize */) => { - let file_size = self.dentry.vnode().inode().metadata().size as isize; + let file_size = self.dentry.vnode().len() as isize; assert!(file_size >= 0); file_size .checked_add(off) @@ -125,7 +112,7 @@ impl InodeHandle_ { pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result { let mut offset = self.offset.lock(); let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer); - let written_size = self.dentry.vnode().inode().readdir(&mut dir_writer_ctx)?; + let written_size = self.dentry.vnode().readdir(&mut dir_writer_ctx)?; *offset = dir_writer_ctx.pos(); Ok(written_size) } diff --git a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs index 6e9ed09da..37872b4e0 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs @@ -10,6 +10,11 @@ impl InodeHandle { self.0.read(buf) } + #[require(R > Read)] + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + self.0.read_to_end(buf) + } + #[require(R > Write)] pub fn write(&self, buf: &[u8]) -> Result { self.0.write(buf) diff --git a/src/services/libs/jinux-std/src/fs/file_handle/mod.rs b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs index e3682bc19..84202a8fa 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle/mod.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs @@ -70,7 +70,7 @@ impl FileHandle { pub fn metadata(&self) -> Metadata { match &self.inner { Inner::File(file) => file.metadata(), - Inner::Inode(inode_handle) => inode_handle.dentry().vnode().inode().metadata(), + Inner::Inode(inode_handle) => inode_handle.dentry().vnode().metadata(), } } diff --git a/src/services/libs/jinux-std/src/fs/fs_resolver.rs b/src/services/libs/jinux-std/src/fs/fs_resolver.rs index 9bbfae752..6b5803215 100644 --- a/src/services/libs/jinux-std/src/fs/fs_resolver.rs +++ b/src/services/libs/jinux-std/src/fs/fs_resolver.rs @@ -11,7 +11,14 @@ use super::utils::{ }; lazy_static! { - static ref ROOT_FS: Arc = RamFS::new(); + static ref RAM_FS: Arc = RamFS::new(); + static ref ROOT_DENTRY: Arc = { + fn init() -> Result> { + let root_vnode = Vnode::new(RAM_FS.root_inode())?; + Ok(Dentry::new_root(root_vnode)) + } + init().unwrap() + }; } pub struct FsResolver { @@ -29,15 +36,11 @@ impl Clone for FsResolver { } impl FsResolver { - pub fn new() -> Result { - let root = { - let root_vnode = Vnode::new(ROOT_FS.root_inode())?; - Dentry::new_root(root_vnode) - }; - Ok(Self { - root: root.clone(), - cwd: root, - }) + pub fn new() -> Self { + Self { + root: ROOT_DENTRY.clone(), + cwd: ROOT_DENTRY.clone(), + } } /// Get the root directory @@ -65,8 +68,8 @@ impl FsResolver { let follow_tail_link = !creation_flags.contains(CreationFlags::O_NOFOLLOW); let dentry = match self.lookup_inner(path, follow_tail_link) { Ok(dentry) => { - let inode = dentry.vnode().inode(); - if inode.metadata().type_ == InodeType::SymLink + let vnode = dentry.vnode(); + if vnode.inode_type() == InodeType::SymLink && !status_flags.contains(StatusFlags::O_PATH) { return_errno_with_message!(Errno::ELOOP, "file is a symlink"); @@ -77,7 +80,7 @@ impl FsResolver { return_errno_with_message!(Errno::EEXIST, "file exists"); } if creation_flags.contains(CreationFlags::O_DIRECTORY) - && inode.metadata().type_ != InodeType::Dir + && vnode.inode_type() != InodeType::Dir { return_errno_with_message!( Errno::ENOTDIR, @@ -98,7 +101,7 @@ impl FsResolver { if file_name.ends_with("/") { return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); } - if !dir_dentry.vnode().inode().metadata().mode.is_writable() { + if !dir_dentry.vnode().inode_mode().is_writable() { return_errno_with_message!(Errno::EPERM, "file cannot be created"); } let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?; @@ -181,7 +184,7 @@ impl FsResolver { // Iterate next dentry let next_dentry = dentry.lookup(next_name)?; - let next_type = next_dentry.vnode().inode().metadata().type_; + let next_type = next_dentry.vnode().inode_type(); let next_is_tail = path_remain.is_empty(); // If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. @@ -190,7 +193,7 @@ impl FsResolver { return_errno_with_message!(Errno::ELOOP, "too many symlinks"); } let link_path_remain = { - let mut tmp_link_path = next_dentry.vnode().inode().read_link()?; + let mut tmp_link_path = next_dentry.vnode().read_link()?; if tmp_link_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "empty symlink"); } @@ -279,9 +282,9 @@ impl FsResolver { // Dereference the tail symlinks if needed loop { match dir_dentry.lookup(&base_name.trim_end_matches('/')) { - Ok(dentry) if dentry.vnode().inode().metadata().type_ == InodeType::SymLink => { + Ok(dentry) if dentry.vnode().inode_type() == InodeType::SymLink => { let link = { - let mut link = dentry.vnode().inode().read_link()?; + let mut link = dentry.vnode().read_link()?; if link.is_empty() { return_errno_with_message!(Errno::ENOENT, "invalid symlink"); } diff --git a/src/services/libs/jinux-std/src/fs/ramfs/fs.rs b/src/services/libs/jinux-std/src/fs/ramfs/fs.rs index 33553a652..0becb64fc 100644 --- a/src/services/libs/jinux-std/src/fs/ramfs/fs.rs +++ b/src/services/libs/jinux-std/src/fs/ramfs/fs.rs @@ -301,12 +301,12 @@ impl Inode for RamInode { return_errno_with_message!(Errno::EOPNOTSUPP, "direct write is not supported"); } - fn resize(&self, new_size: usize) -> Result<()> { - if self.0.read().metadata.type_ != InodeType::File { - return_errno_with_message!(Errno::EISDIR, "self is not file"); - } + fn len(&self) -> usize { + self.0.read().metadata.size + } + + fn resize(&self, new_size: usize) { self.0.write().metadata.size = new_size; - Ok(()) } fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { diff --git a/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs b/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs index e9cac550c..5fa33a5a7 100644 --- a/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs +++ b/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use alloc::string::String; use spin::RwLockWriteGuard; -use super::{InodeMode, InodeType, Vnode, NAME_MAX}; +use super::{InodeMode, InodeType, Metadata, Vnode, NAME_MAX}; pub struct Dentry { inner: RwLock, @@ -68,12 +68,12 @@ impl Dentry { self.inner.write().parent = Some(Arc::downgrade(parent)); } - pub fn vnode(&self) -> &Vnode { + pub(in crate::fs) fn vnode(&self) -> &Vnode { &self.vnode } pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { - if self.vnode.inode().metadata().type_ != InodeType::Dir { + if self.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut inner = self.inner.write(); @@ -81,7 +81,7 @@ impl Dentry { return_errno!(Errno::EEXIST); } let child = { - let vnode = Vnode::new(self.vnode.inode().mknod(name, type_, mode)?)?; + let vnode = self.vnode.mknod(name, type_, mode)?; Dentry::new(name, vnode, Some(inner.this.clone())) }; inner.children.insert(String::from(name), child.clone()); @@ -89,7 +89,7 @@ impl Dentry { } pub fn lookup(&self, name: &str) -> Result> { - if self.vnode.inode().metadata().type_ != InodeType::Dir { + if self.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } if name.len() > NAME_MAX { @@ -104,7 +104,7 @@ impl Dentry { if let Some(dentry) = inner.children.get(name) { dentry.clone() } else { - let vnode = Vnode::new(self.vnode.inode().lookup(name)?)?; + let vnode = self.vnode.lookup(name)?; let dentry = Dentry::new(name, vnode, Some(inner.this.clone())); inner.children.insert(String::from(name), dentry.clone()); dentry @@ -115,7 +115,7 @@ impl Dentry { } pub fn link(&self, old: &Arc, name: &str) -> Result<()> { - if self.vnode.inode().metadata().type_ != InodeType::Dir { + if self.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut inner = self.inner.write(); @@ -123,38 +123,51 @@ impl Dentry { return_errno!(Errno::EEXIST); } let target_vnode = old.vnode(); - self.vnode.inode().link(target_vnode.inode(), name)?; + self.vnode.link(target_vnode, name)?; let new_dentry = Self::new(name, target_vnode.clone(), Some(inner.this.clone())); inner.children.insert(String::from(name), new_dentry); Ok(()) } pub fn unlink(&self, name: &str) -> Result<()> { - if self.vnode.inode().metadata().type_ != InodeType::Dir { + if self.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut inner = self.inner.write(); - self.vnode.inode().unlink(name)?; + self.vnode.unlink(name)?; inner.children.remove(name); Ok(()) } pub fn rmdir(&self, name: &str) -> Result<()> { - if self.vnode.inode().metadata().type_ != InodeType::Dir { + if self.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut inner = self.inner.write(); - self.vnode.inode().rmdir(name)?; + self.vnode.rmdir(name)?; inner.children.remove(name); Ok(()) } + pub fn read_link(&self) -> Result { + if self.vnode.inode_type() != InodeType::SymLink { + return_errno!(Errno::EINVAL); + } + self.vnode.read_link() + } + + pub fn write_link(&self, target: &str) -> Result<()> { + if self.vnode.inode_type() != InodeType::SymLink { + return_errno!(Errno::EINVAL); + } + self.vnode.write_link(target) + } + pub fn rename(&self, old_name: &str, new_dir: &Arc, new_name: &str) -> Result<()> { if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." { return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory"); } - if self.vnode.inode().metadata().type_ != InodeType::Dir - || new_dir.vnode.inode().metadata().type_ != InodeType::Dir + if self.vnode.inode_type() != InodeType::Dir || new_dir.vnode.inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -168,12 +181,10 @@ impl Dentry { let dentry = if let Some(dentry) = inner.children.get(old_name) { dentry.clone() } else { - let vnode = Vnode::new(self.vnode.inode().lookup(old_name)?)?; + let vnode = self.vnode.lookup(old_name)?; Dentry::new(old_name, vnode, Some(inner.this.clone())) }; - self.vnode - .inode() - .rename(old_name, self.vnode.inode(), new_name)?; + self.vnode.rename(old_name, &self.vnode, new_name)?; inner.children.remove(old_name); dentry.set_name(new_name); inner.children.insert(String::from(new_name), dentry); @@ -183,12 +194,10 @@ impl Dentry { let dentry = if let Some(dentry) = self_inner.children.get(old_name) { dentry.clone() } else { - let vnode = Vnode::new(self.vnode.inode().lookup(old_name)?)?; + let vnode = self.vnode.lookup(old_name)?; Dentry::new(old_name, vnode, Some(self_inner.this.clone())) }; - self.vnode - .inode() - .rename(old_name, new_dir.vnode.inode(), new_name)?; + self.vnode.rename(old_name, &new_dir.vnode, new_name)?; self_inner.children.remove(old_name); dentry.set_name(new_name); dentry.set_parent(&new_dir.this()); @@ -199,6 +208,22 @@ impl Dentry { Ok(()) } + pub fn inode_metadata(&self) -> Metadata { + self.vnode.metadata() + } + + pub fn inode_type(&self) -> InodeType { + self.vnode.inode_type() + } + + pub fn inode_mode(&self) -> InodeMode { + self.vnode.inode_mode() + } + + pub fn inode_len(&self) -> usize { + self.vnode.len() + } + pub fn abs_path(&self) -> String { let mut path = self.name(); let mut dentry = self.this(); diff --git a/src/services/libs/jinux-std/src/fs/utils/inode.rs b/src/services/libs/jinux-std/src/fs/utils/inode.rs index 95e3032c4..777b3c712 100644 --- a/src/services/libs/jinux-std/src/fs/utils/inode.rs +++ b/src/services/libs/jinux-std/src/fs/utils/inode.rs @@ -159,7 +159,9 @@ pub struct Timespec { } pub trait Inode: Any + Sync + Send { - fn resize(&self, new_size: usize) -> Result<()>; + fn len(&self) -> usize; + + fn resize(&self, new_size: usize); fn metadata(&self) -> Metadata; diff --git a/src/services/libs/jinux-std/src/fs/utils/vnode.rs b/src/services/libs/jinux-std/src/fs/utils/vnode.rs index 29494edb7..3c827cc67 100644 --- a/src/services/libs/jinux-std/src/fs/utils/vnode.rs +++ b/src/services/libs/jinux-std/src/fs/utils/vnode.rs @@ -1,31 +1,186 @@ use crate::prelude::*; -use super::{Inode, PageCacheManager}; +use super::{DirentWriterContext, Inode, InodeMode, InodeType, Metadata, PageCacheManager}; use crate::rights::Rights; use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions}; +use alloc::string::String; +use jinux_frame::vm::VmIo; /// VFS-level representation of an inode #[derive(Clone)] pub struct Vnode { + // The RwLock is to maintain the correct file length for concurrent read or write. + inner: Arc>, +} + +struct Inner { inode: Arc, - pages: Vmo, + page_cache: Vmo, + page_cache_manager: Arc, } impl Vnode { pub fn new(inode: Arc) -> Result { let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode))); - let pages = VmoOptions::::new(inode.metadata().size) + let page_cache = VmoOptions::::new(inode.len()) .flags(VmoFlags::RESIZABLE) - .pager(page_cache_manager) + .pager(page_cache_manager.clone()) .alloc()?; - Ok(Self { inode, pages }) + Ok(Self { + inner: Arc::new(RwLock::new(Inner { + inode, + page_cache, + page_cache_manager, + })), + }) } - pub fn pages(&self) -> &Vmo { - &self.pages + pub fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EINVAL); + } + let inner = self.inner.write(); + let file_len = inner.inode.len(); + let should_expand_len = offset + buf.len() > file_len; + if should_expand_len { + inner.page_cache.resize(offset + buf.len())?; + } + inner.page_cache.write_bytes(offset, buf)?; + if should_expand_len { + inner.inode.resize(offset + buf.len()); + } + Ok(buf.len()) } - pub fn inode(&self) -> &Arc { - &self.inode + pub fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EINVAL); + } + let inner = self.inner.write(); + let file_len = inner.inode.len(); + if offset + buf.len() > file_len { + inner.page_cache.resize(offset + buf.len())?; + } + // Flush the dirty pages if necessary. + // inner.page_cache_manager.flush(offset..offset + buf.len())?; + // TODO: Update the related page state to invalid to reload the content from inode + // for upcoming read or write. + inner.inode.write_at(offset, buf) + } + + pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EISDIR); + } + let inner = self.inner.read(); + let (offset, read_len) = { + let file_len = inner.inode.len(); + let start = file_len.min(offset); + let end = file_len.min(offset + buf.len()); + (start, end - start) + }; + inner.page_cache.read_bytes(offset, &mut buf[..read_len])?; + Ok(read_len) + } + + pub fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EISDIR); + } + let inner = self.inner.read(); + // Flush the dirty pages if necessary. + // inner.page_cache_manager.flush(offset..offset + buf.len())?; + inner.inode.read_at(offset, buf) + } + + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EISDIR); + } + let inner = self.inner.read(); + let file_len = inner.inode.len(); + if buf.len() < file_len { + buf.resize(file_len, 0); + } + inner.page_cache.read_bytes(0, &mut buf[..file_len])?; + Ok(file_len) + } + + pub fn read_direct_to_end(&self, buf: &mut Vec) -> Result { + let type_ = self.inode_type(); + if type_ != InodeType::File && type_ != InodeType::Socket { + return_errno!(Errno::EISDIR); + } + let inner = self.inner.read(); + let file_len = inner.inode.len(); + if buf.len() < file_len { + buf.resize(file_len, 0); + } + // Flush the dirty pages if necessary. + // inner.page_cache_manager.flush(..file_size)?; + let len = inner.inode.read_at(0, &mut buf[..file_len])?; + Ok(len) + } + + pub fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result { + let inode = self.inner.read().inode.mknod(name, type_, mode)?; + Self::new(inode) + } + + pub fn lookup(&self, name: &str) -> Result { + let inode = self.inner.read().inode.lookup(name)?; + Self::new(inode) + } + + pub fn link(&self, old: &Vnode, name: &str) -> Result<()> { + self.inner.read().inode.link(&old.inner.read().inode, name) + } + + pub fn unlink(&self, name: &str) -> Result<()> { + self.inner.read().inode.unlink(name) + } + + pub fn rmdir(&self, name: &str) -> Result<()> { + self.inner.read().inode.rmdir(name) + } + + pub fn rename(&self, old_name: &str, target: &Vnode, new_name: &str) -> Result<()> { + self.inner + .read() + .inode + .rename(old_name, &target.inner.read().inode, new_name) + } + + pub fn read_link(&self) -> Result { + self.inner.read().inode.read_link() + } + + pub fn write_link(&self, target: &str) -> Result<()> { + self.inner.write().inode.write_link(target) + } + + pub fn readdir(&self, ctx: &mut DirentWriterContext) -> Result { + self.inner.read().inode.readdir(ctx) + } + + pub fn metadata(&self) -> Metadata { + self.inner.read().inode.metadata() + } + + pub fn inode_type(&self) -> InodeType { + self.inner.read().inode.metadata().type_ + } + + pub fn inode_mode(&self) -> InodeMode { + self.inner.read().inode.metadata().mode + } + + pub fn len(&self) -> usize { + self.inner.read().inode.len() } } diff --git a/src/services/libs/jinux-std/src/process/mod.rs b/src/services/libs/jinux-std/src/process/mod.rs index 1c07324d3..2962f3ed0 100644 --- a/src/services/libs/jinux-std/src/process/mod.rs +++ b/src/services/libs/jinux-std/src/process/mod.rs @@ -196,7 +196,7 @@ impl Process { let pid = thread.tid(); let user_vm = UserVm::new(); let file_table = FileTable::new_with_stdio(); - let fs = FsResolver::new().unwrap(); + let fs = FsResolver::new(); let sig_dispositions = SigDispositions::new(); let process = Process::new( @@ -231,7 +231,7 @@ impl Process { let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone()); let pid = thread.tid(); let file_table = FileTable::new(); - let fs = FsResolver::new().unwrap(); + let fs = FsResolver::new(); let sig_dispositions = SigDispositions::new(); // FIXME: kernel process does not need root vmar let root_vmar = Vmar::::new_root().unwrap(); diff --git a/src/services/libs/jinux-std/src/syscall/readlink.rs b/src/services/libs/jinux-std/src/syscall/readlink.rs index 8eafc38ac..f0bb514d6 100644 --- a/src/services/libs/jinux-std/src/syscall/readlink.rs +++ b/src/services/libs/jinux-std/src/syscall/readlink.rs @@ -44,7 +44,7 @@ pub fn sys_readlinkat( let fs_path = FsPath::new(dirfd, pathname.as_ref())?; current.fs().read().lookup_no_follow(&fs_path)? }; - let linkpath = dentry.vnode().inode().read_link()?; + let linkpath = dentry.read_link()?; let bytes = linkpath.as_bytes(); let write_len = bytes.len().min(usr_buf_len); write_bytes_to_user(usr_buf_addr, &bytes[..write_len])?; diff --git a/src/services/libs/jinux-std/src/syscall/rename.rs b/src/services/libs/jinux-std/src/syscall/rename.rs index 94327de43..a348f25b3 100644 --- a/src/services/libs/jinux-std/src/syscall/rename.rs +++ b/src/services/libs/jinux-std/src/syscall/rename.rs @@ -42,9 +42,7 @@ pub fn sys_renameat( if new_pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "newpath is empty"); } - if new_pathname.ends_with("/") - && old_dentry.vnode().inode().metadata().type_ != InodeType::Dir - { + if new_pathname.ends_with("/") && old_dentry.inode_type() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir"); } let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?; diff --git a/src/services/libs/jinux-std/src/syscall/stat.rs b/src/services/libs/jinux-std/src/syscall/stat.rs index f4a88c804..8afff46ca 100644 --- a/src/services/libs/jinux-std/src/syscall/stat.rs +++ b/src/services/libs/jinux-std/src/syscall/stat.rs @@ -65,7 +65,7 @@ pub fn sys_fstatat( fs.lookup(&fs_path)? } }; - let stat = Stat::from(dentry.vnode().inode().metadata()); + let stat = Stat::from(dentry.inode_metadata()); write_val_to_user(stat_buf_ptr, &stat)?; Ok(SyscallReturn::Return(0)) } diff --git a/src/services/libs/jinux-std/src/syscall/symlink.rs b/src/services/libs/jinux-std/src/syscall/symlink.rs index 64cce3a39..d264426b2 100644 --- a/src/services/libs/jinux-std/src/syscall/symlink.rs +++ b/src/services/libs/jinux-std/src/syscall/symlink.rs @@ -46,7 +46,7 @@ pub fn sys_symlinkat( InodeType::SymLink, InodeMode::from_bits_truncate(0o777), )?; - new_dentry.vnode().inode().write_link(&target)?; + new_dentry.write_link(&target)?; Ok(SyscallReturn::Return(0)) }