From 98bf3d48454931d27db1b182e9200aeb3cd658f0 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Wed, 13 Sep 2023 12:07:58 +0800 Subject: [PATCH] Remove Vnode to let the fs use PageCache for itself --- services/libs/jinux-std/src/device/pty/mod.rs | 2 +- .../libs/jinux-std/src/fs/devpts/master.rs | 20 +- services/libs/jinux-std/src/fs/devpts/mod.rs | 14 +- services/libs/jinux-std/src/fs/devpts/ptmx.rs | 20 +- .../libs/jinux-std/src/fs/devpts/slave.rs | 20 +- services/libs/jinux-std/src/fs/fs_resolver.rs | 16 +- .../jinux-std/src/fs/inode_handle/dyn_cap.rs | 14 +- .../libs/jinux-std/src/fs/inode_handle/mod.rs | 20 +- services/libs/jinux-std/src/fs/procfs/mod.rs | 2 +- .../jinux-std/src/fs/procfs/template/dir.rs | 16 +- .../jinux-std/src/fs/procfs/template/file.rs | 26 +- .../jinux-std/src/fs/procfs/template/mod.rs | 4 + .../jinux-std/src/fs/procfs/template/sym.rs | 26 +- services/libs/jinux-std/src/fs/ramfs/fs.rs | 169 +++++++--- services/libs/jinux-std/src/fs/ramfs/mod.rs | 1 + services/libs/jinux-std/src/fs/rootfs.rs | 21 +- .../libs/jinux-std/src/fs/utils/dentry.rs | 109 +++---- services/libs/jinux-std/src/fs/utils/fs.rs | 6 - services/libs/jinux-std/src/fs/utils/inode.rs | 82 ++++- services/libs/jinux-std/src/fs/utils/mod.rs | 2 - services/libs/jinux-std/src/fs/utils/mount.rs | 15 +- .../libs/jinux-std/src/fs/utils/page_cache.rs | 77 +++-- services/libs/jinux-std/src/fs/utils/vnode.rs | 300 ------------------ .../jinux-std/src/net/socket/unix/addr.rs | 10 +- .../src/net/socket/unix/stream/listener.rs | 4 +- .../process/program_loader/elf/load_elf.rs | 8 +- .../src/process/program_loader/mod.rs | 4 +- services/libs/jinux-std/src/syscall/mmap.rs | 4 +- .../libs/jinux-std/src/syscall/readlink.rs | 2 +- .../libs/jinux-std/src/syscall/symlink.rs | 2 +- 30 files changed, 483 insertions(+), 533 deletions(-) delete mode 100644 services/libs/jinux-std/src/fs/utils/vnode.rs diff --git a/services/libs/jinux-std/src/device/pty/mod.rs b/services/libs/jinux-std/src/device/pty/mod.rs index aac3510ab..a6a817372 100644 --- a/services/libs/jinux-std/src/device/pty/mod.rs +++ b/services/libs/jinux-std/src/device/pty/mod.rs @@ -27,7 +27,7 @@ pub fn init() -> Result<()> { InodeType::SymLink, InodeMode::from_bits_truncate(0o777), )?; - ptmx.write_link("pts/ptmx")?; + ptmx.inode().write_link("pts/ptmx")?; Ok(()) } diff --git a/services/libs/jinux-std/src/fs/devpts/master.rs b/services/libs/jinux-std/src/fs/devpts/master.rs index 324d35b83..bfddebfc6 100644 --- a/services/libs/jinux-std/src/fs/devpts/master.rs +++ b/services/libs/jinux-std/src/fs/devpts/master.rs @@ -46,6 +46,16 @@ impl Inode for PtyMasterInode { self.0.ptmx().metadata() } + fn type_(&self) -> InodeType { + self.0.ptmx().metadata().type_ + } + + fn mode(&self) -> InodeMode { + self.0.ptmx().metadata().mode + } + + fn set_mode(&self, mode: InodeMode) {} + fn atime(&self) -> Duration { self.0.ptmx().metadata().atime } @@ -58,8 +68,6 @@ impl Inode for PtyMasterInode { fn set_mtime(&self, time: Duration) {} - fn set_mode(&self, mode: InodeMode) {} - fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> { Ok(()) } @@ -72,10 +80,18 @@ impl Inode for PtyMasterInode { self.0.read(buf) } + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + self.0.read(buf) + } + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { self.0.write(buf) } + fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + self.0.write(buf) + } + fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { self.0.ioctl(cmd, arg) } diff --git a/services/libs/jinux-std/src/fs/devpts/mod.rs b/services/libs/jinux-std/src/fs/devpts/mod.rs index e07d8be5b..f960872e7 100644 --- a/services/libs/jinux-std/src/fs/devpts/mod.rs +++ b/services/libs/jinux-std/src/fs/devpts/mod.rs @@ -94,7 +94,7 @@ impl FileSystem for DevPts { } fn flags(&self) -> FsFlags { - FsFlags::NO_PAGECACHE + FsFlags::empty() } } @@ -148,6 +148,16 @@ impl Inode for RootInode { self.metadata.clone() } + fn type_(&self) -> InodeType { + self.metadata.type_ + } + + fn mode(&self) -> InodeMode { + self.metadata.mode + } + + fn set_mode(&self, mode: InodeMode) {} + fn atime(&self) -> Duration { self.metadata.atime } @@ -160,8 +170,6 @@ impl Inode for RootInode { fn set_mtime(&self, time: Duration) {} - fn set_mode(&self, mode: InodeMode) {} - fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { Err(Error::new(Errno::EPERM)) } diff --git a/services/libs/jinux-std/src/fs/devpts/ptmx.rs b/services/libs/jinux-std/src/fs/devpts/ptmx.rs index b1d538696..fcba7bab2 100644 --- a/services/libs/jinux-std/src/fs/devpts/ptmx.rs +++ b/services/libs/jinux-std/src/fs/devpts/ptmx.rs @@ -66,6 +66,16 @@ impl Inode for Ptmx { self.metadata.clone() } + fn type_(&self) -> InodeType { + self.metadata.type_ + } + + fn mode(&self) -> InodeMode { + self.metadata.mode + } + + fn set_mode(&self, mode: InodeMode) {} + fn atime(&self) -> Duration { self.metadata.atime } @@ -78,8 +88,6 @@ impl Inode for Ptmx { fn set_mtime(&self, time: Duration) {} - fn set_mode(&self, mode: InodeMode) {} - fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> { Ok(()) } @@ -92,10 +100,18 @@ impl Inode for Ptmx { Ok(0) } + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + Ok(0) + } + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { Ok(0) } + fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + Ok(0) + } + fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { Ok(0) } diff --git a/services/libs/jinux-std/src/fs/devpts/slave.rs b/services/libs/jinux-std/src/fs/devpts/slave.rs index 125dcf5c3..83e7ffc99 100644 --- a/services/libs/jinux-std/src/fs/devpts/slave.rs +++ b/services/libs/jinux-std/src/fs/devpts/slave.rs @@ -50,6 +50,16 @@ impl Inode for PtySlaveInode { self.metadata.clone() } + fn type_(&self) -> InodeType { + self.metadata.type_ + } + + fn mode(&self) -> InodeMode { + self.metadata.mode + } + + fn set_mode(&self, mode: InodeMode) {} + fn atime(&self) -> Duration { self.metadata.atime } @@ -62,8 +72,6 @@ impl Inode for PtySlaveInode { fn set_mtime(&self, time: Duration) {} - fn set_mode(&self, mode: InodeMode) {} - fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> { Ok(()) } @@ -76,10 +84,18 @@ impl Inode for PtySlaveInode { self.device.read(buf) } + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + self.device.read(buf) + } + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { self.device.write(buf) } + fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + self.device.write(buf) + } + fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { self.device.ioctl(cmd, arg) } diff --git a/services/libs/jinux-std/src/fs/fs_resolver.rs b/services/libs/jinux-std/src/fs/fs_resolver.rs index faeb05281..50aaf5565 100644 --- a/services/libs/jinux-std/src/fs/fs_resolver.rs +++ b/services/libs/jinux-std/src/fs/fs_resolver.rs @@ -62,8 +62,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 vnode = dentry.vnode(); - if vnode.inode_type() == InodeType::SymLink + let inode = dentry.inode(); + if inode.type_() == InodeType::SymLink && !status_flags.contains(StatusFlags::O_PATH) { return_errno_with_message!(Errno::ELOOP, "file is a symlink"); @@ -74,7 +74,7 @@ impl FsResolver { return_errno_with_message!(Errno::EEXIST, "file exists"); } if creation_flags.contains(CreationFlags::O_DIRECTORY) - && vnode.inode_type() != InodeType::Dir + && inode.type_() != InodeType::Dir { return_errno_with_message!( Errno::ENOTDIR, @@ -95,7 +95,7 @@ impl FsResolver { if file_name.ends_with('/') { return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); } - if !dir_dentry.vnode().inode_mode().is_writable() { + if !dir_dentry.inode_mode().is_writable() { return_errno_with_message!(Errno::EACCES, "file cannot be created"); } dir_dentry.create(&file_name, InodeType::File, inode_mode)? @@ -177,7 +177,7 @@ impl FsResolver { // Iterate next dentry let next_dentry = dentry.lookup(next_name)?; - let next_type = next_dentry.vnode().inode_type(); + let next_type = next_dentry.inode_type(); let next_is_tail = path_remain.is_empty(); // If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. @@ -186,7 +186,7 @@ impl FsResolver { return_errno_with_message!(Errno::ELOOP, "too many symlinks"); } let link_path_remain = { - let mut tmp_link_path = next_dentry.vnode().read_link()?; + let mut tmp_link_path = next_dentry.inode().read_link()?; if tmp_link_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "empty symlink"); } @@ -275,9 +275,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_type() == InodeType::SymLink => { + Ok(dentry) if dentry.inode_type() == InodeType::SymLink => { let link = { - let mut link = dentry.vnode().read_link()?; + let mut link = dentry.inode().read_link()?; if link.is_empty() { return_errno_with_message!(Errno::ENOENT, "invalid symlink"); } diff --git a/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs b/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs index 0042194f2..b286aa581 100644 --- a/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs +++ b/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs @@ -11,14 +11,14 @@ impl InodeHandle { access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { - let vnode = dentry.vnode(); - if access_mode.is_readable() && !vnode.inode_mode().is_readable() { + let inode = dentry.inode(); + if access_mode.is_readable() && !inode.mode().is_readable() { return_errno_with_message!(Errno::EACCES, "File is not readable"); } - if access_mode.is_writable() && !vnode.inode_mode().is_writable() { + if access_mode.is_writable() && !inode.mode().is_writable() { return_errno_with_message!(Errno::EACCES, "File is not writable"); } - if access_mode.is_writable() && vnode.inode_type() == InodeType::Dir { + if access_mode.is_writable() && inode.type_() == InodeType::Dir { return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write"); } let inner = Arc::new(InodeHandle_ { @@ -75,15 +75,15 @@ impl FileLike for InodeHandle { } fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents { - self.dentry().vnode().poll(mask, poller) + self.dentry().inode().poll(mask, poller) } fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { - self.dentry().vnode().ioctl(cmd, arg) + self.dentry().inode().ioctl(cmd, arg) } fn metadata(&self) -> Metadata { - self.dentry().vnode().metadata() + self.dentry().inode_metadata() } fn status_flags(&self) -> StatusFlags { diff --git a/services/libs/jinux-std/src/fs/inode_handle/mod.rs b/services/libs/jinux-std/src/fs/inode_handle/mod.rs index 2608c36c9..aa9101f16 100644 --- a/services/libs/jinux-std/src/fs/inode_handle/mod.rs +++ b/services/libs/jinux-std/src/fs/inode_handle/mod.rs @@ -26,9 +26,9 @@ impl InodeHandle_ { pub fn read(&self, buf: &mut [u8]) -> Result { let mut offset = self.offset.lock(); let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.vnode().read_direct_at(*offset, buf)? + self.dentry.inode().read_direct_at(*offset, buf)? } else { - self.dentry.vnode().read_at(*offset, buf)? + self.dentry.inode().read_at(*offset, buf)? }; *offset += len; @@ -38,12 +38,12 @@ impl InodeHandle_ { pub fn write(&self, buf: &[u8]) -> Result { let mut offset = self.offset.lock(); if self.status_flags().contains(StatusFlags::O_APPEND) { - *offset = self.dentry.vnode().len(); + *offset = self.dentry.inode_len(); } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.vnode().write_direct_at(*offset, buf)? + self.dentry.inode().write_direct_at(*offset, buf)? } else { - self.dentry.vnode().write_at(*offset, buf)? + self.dentry.inode().write_at(*offset, buf)? }; *offset += len; @@ -52,9 +52,9 @@ impl InodeHandle_ { pub fn read_to_end(&self, buf: &mut Vec) -> Result { let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.vnode().read_direct_to_end(buf)? + self.dentry.inode().read_direct_to_end(buf)? } else { - self.dentry.vnode().read_to_end(buf)? + self.dentry.inode().read_to_end(buf)? }; Ok(len) } @@ -69,7 +69,7 @@ impl InodeHandle_ { off as isize } SeekFrom::End(off /* as isize */) => { - let file_size = self.dentry.vnode().len() as isize; + let file_size = self.dentry.inode_len() as isize; assert!(file_size >= 0); file_size .checked_add(off) @@ -94,7 +94,7 @@ impl InodeHandle_ { } pub fn len(&self) -> usize { - self.dentry.vnode().len() + self.dentry.inode_len() } pub fn access_mode(&self) -> AccessMode { @@ -113,7 +113,7 @@ impl InodeHandle_ { pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result { let mut offset = self.offset.lock(); - let read_cnt = self.dentry.vnode().readdir_at(*offset, visitor)?; + let read_cnt = self.dentry.inode().readdir_at(*offset, visitor)?; *offset += read_cnt; Ok(read_cnt) } diff --git a/services/libs/jinux-std/src/fs/procfs/mod.rs b/services/libs/jinux-std/src/fs/procfs/mod.rs index 965b1c84f..2614b307b 100644 --- a/services/libs/jinux-std/src/fs/procfs/mod.rs +++ b/services/libs/jinux-std/src/fs/procfs/mod.rs @@ -61,7 +61,7 @@ impl FileSystem for ProcFS { } fn flags(&self) -> FsFlags { - FsFlags::NO_PAGECACHE + FsFlags::empty() } } diff --git a/services/libs/jinux-std/src/fs/procfs/template/dir.rs b/services/libs/jinux-std/src/fs/procfs/template/dir.rs index 3da24c62b..2f00ee35e 100644 --- a/services/libs/jinux-std/src/fs/procfs/template/dir.rs +++ b/services/libs/jinux-std/src/fs/procfs/template/dir.rs @@ -64,6 +64,18 @@ impl Inode for ProcDir { self.info.metadata() } + fn type_(&self) -> InodeType { + InodeType::Dir + } + + fn mode(&self) -> InodeMode { + self.info.mode() + } + + fn set_mode(&self, mode: InodeMode) { + self.info.set_mode(mode) + } + fn atime(&self) -> Duration { self.info.atime() } @@ -80,10 +92,6 @@ impl Inode for ProcDir { self.info.set_mtime(time) } - fn set_mode(&self, mode: InodeMode) { - self.info.set_mode(mode) - } - fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result> { Err(Error::new(Errno::EPERM)) } diff --git a/services/libs/jinux-std/src/fs/procfs/template/file.rs b/services/libs/jinux-std/src/fs/procfs/template/file.rs index 05d4196b4..cb6fe1179 100644 --- a/services/libs/jinux-std/src/fs/procfs/template/file.rs +++ b/services/libs/jinux-std/src/fs/procfs/template/file.rs @@ -1,7 +1,7 @@ use core::time::Duration; use jinux_frame::vm::VmFrame; -use crate::fs::utils::{FileSystem, Inode, InodeMode, IoctlCmd, Metadata}; +use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata}; use crate::prelude::*; use super::{ProcFS, ProcInodeInfo}; @@ -37,6 +37,18 @@ impl Inode for ProcFile { self.info.metadata() } + fn type_(&self) -> InodeType { + InodeType::File + } + + fn mode(&self) -> InodeMode { + self.info.mode() + } + + fn set_mode(&self, mode: InodeMode) { + self.info.set_mode(mode) + } + fn atime(&self) -> Duration { self.info.atime() } @@ -53,10 +65,6 @@ impl Inode for ProcFile { self.info.set_mtime(time) } - fn set_mode(&self, mode: InodeMode) { - self.info.set_mode(mode) - } - fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> { unreachable!() } @@ -74,10 +82,18 @@ impl Inode for ProcFile { Ok(len) } + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + self.read_at(offset, buf) + } + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { Err(Error::new(Errno::EPERM)) } + fn write_direct_at(&self, _offset: usize, _buf: &[u8]) -> Result { + Err(Error::new(Errno::EPERM)) + } + fn read_link(&self) -> Result { Err(Error::new(Errno::EINVAL)) } diff --git a/services/libs/jinux-std/src/fs/procfs/template/mod.rs b/services/libs/jinux-std/src/fs/procfs/template/mod.rs index b310cdf26..cc189746c 100644 --- a/services/libs/jinux-std/src/fs/procfs/template/mod.rs +++ b/services/libs/jinux-std/src/fs/procfs/template/mod.rs @@ -58,6 +58,10 @@ impl ProcInodeInfo { self.metadata.write().mtime = time; } + pub fn mode(&self) -> InodeMode { + self.metadata.read().mode + } + pub fn set_mode(&self, mode: InodeMode) { self.metadata.write().mode = mode; } diff --git a/services/libs/jinux-std/src/fs/procfs/template/sym.rs b/services/libs/jinux-std/src/fs/procfs/template/sym.rs index 9210ea5dc..355a02904 100644 --- a/services/libs/jinux-std/src/fs/procfs/template/sym.rs +++ b/services/libs/jinux-std/src/fs/procfs/template/sym.rs @@ -1,7 +1,7 @@ use core::time::Duration; use jinux_frame::vm::VmFrame; -use crate::fs::utils::{FileSystem, Inode, InodeMode, IoctlCmd, Metadata}; +use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata}; use crate::prelude::*; use super::{ProcFS, ProcInodeInfo}; @@ -37,6 +37,18 @@ impl Inode for ProcSym { self.info.metadata() } + fn type_(&self) -> InodeType { + InodeType::SymLink + } + + fn mode(&self) -> InodeMode { + self.info.mode() + } + + fn set_mode(&self, mode: InodeMode) { + self.info.set_mode(mode) + } + fn atime(&self) -> Duration { self.info.atime() } @@ -53,10 +65,6 @@ impl Inode for ProcSym { self.info.set_mtime(time) } - fn set_mode(&self, mode: InodeMode) { - self.info.set_mode(mode) - } - fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> { Err(Error::new(Errno::EPERM)) } @@ -69,10 +77,18 @@ impl Inode for ProcSym { Err(Error::new(Errno::EPERM)) } + fn read_direct_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { + Err(Error::new(Errno::EPERM)) + } + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { Err(Error::new(Errno::EPERM)) } + fn write_direct_at(&self, _offset: usize, _buf: &[u8]) -> Result { + Err(Error::new(Errno::EPERM)) + } + fn read_link(&self) -> Result { self.inner.read_link() } diff --git a/services/libs/jinux-std/src/fs/ramfs/fs.rs b/services/libs/jinux-std/src/fs/ramfs/fs.rs index 132d0a7f7..f5894b797 100644 --- a/services/libs/jinux-std/src/fs/ramfs/fs.rs +++ b/services/libs/jinux-std/src/fs/ramfs/fs.rs @@ -1,49 +1,41 @@ -use crate::events::IoEvents; -use crate::prelude::*; -use crate::process::signal::Poller; use alloc::str; -use alloc::string::String; use core::sync::atomic::{AtomicUsize, Ordering}; use core::time::Duration; use jinux_frame::sync::{RwLock, RwLockWriteGuard}; -use jinux_frame::vm::VmFrame; +use jinux_frame::vm::{VmFrame, VmIo}; +use jinux_rights::Full; use jinux_util::slot_vec::SlotVec; use super::*; +use crate::events::IoEvents; use crate::fs::device::Device; use crate::fs::utils::{ - DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, - SuperBlock, NAME_MAX, + DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, PageCache, + SuperBlock, }; +use crate::prelude::*; +use crate::process::signal::Poller; +use crate::vm::vmo::Vmo; /// A volatile file system whose data and metadata exists only in memory. pub struct RamFS { metadata: RwLock, root: Arc, inode_allocator: AtomicUsize, - flags: FsFlags, } impl RamFS { - pub fn new(use_pagecache: bool) -> Arc { + pub fn new() -> Arc { let sb = SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX); let root = Arc::new(RamInode(RwLock::new(Inode_::new_dir( ROOT_INO, InodeMode::from_bits_truncate(0o755), &sb, )))); - let flags = { - let mut flags = FsFlags::DENTRY_UNEVICTABLE; - if !use_pagecache { - flags |= FsFlags::NO_PAGECACHE; - } - flags - }; let ramfs = Arc::new(Self { metadata: RwLock::new(sb), root, inode_allocator: AtomicUsize::new(ROOT_INO + 1), - flags, }); let mut root = ramfs.root.0.write(); root.inner @@ -78,7 +70,7 @@ impl FileSystem for RamFS { } fn flags(&self) -> FsFlags { - self.flags + FsFlags::DENTRY_UNEVICTABLE } } @@ -101,9 +93,14 @@ impl Inode_ { } } - pub fn new_file(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self { + pub fn new_file( + ino: usize, + mode: InodeMode, + sb: &SuperBlock, + weak_inode: Weak, + ) -> Self { Self { - inner: Inner::File, + inner: Inner::File(PageCache::new(weak_inode).unwrap()), metadata: Metadata::new_file(ino, mode, sb), this: Weak::default(), fs: Weak::default(), @@ -112,7 +109,7 @@ impl Inode_ { pub fn new_symlink(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self { Self { - inner: Inner::SymLink(Str256::from("")), + inner: Inner::SymLink(String::from("")), metadata: Metadata::new_symlink(ino, mode, sb), this: Weak::default(), fs: Weak::default(), @@ -157,18 +154,34 @@ impl Inode_ { self.metadata.size = new_size; self.metadata.blocks = (new_size + BLOCK_SIZE - 1) / BLOCK_SIZE; } + + pub fn inc_nlinks(&mut self) { + self.metadata.nlinks += 1; + } + + pub fn dec_nlinks(&mut self) { + debug_assert!(self.metadata.nlinks > 0); + self.metadata.nlinks -= 1; + } } #[allow(clippy::large_enum_variant)] enum Inner { Dir(DirEntry), - File, - SymLink(Str256), + File(PageCache), + SymLink(String), Device(Arc), Socket, } impl Inner { + fn as_file(&self) -> Option<&PageCache> { + match self { + Inner::File(page_cache) => Some(page_cache), + _ => None, + } + } + fn as_direntry(&self) -> Option<&DirEntry> { match self { Inner::Dir(dir_entry) => Some(dir_entry), @@ -190,7 +203,7 @@ impl Inner { } } - fn as_symlink_mut(&mut self) -> Option<&mut Str256> { + fn as_symlink_mut(&mut self) -> Option<&mut String> { match self { Inner::SymLink(link) => Some(link), _ => None, @@ -235,7 +248,7 @@ impl DirEntry { } else { self.children .iter() - .any(|(child, _)| child == &Str256::from(name)) + .any(|(child, _)| child.as_ref() == name) } } @@ -247,7 +260,7 @@ impl DirEntry { } else { self.children .idxes_and_items() - .find(|(_, (child, _))| child == &Str256::from(name)) + .find(|(_, (child, _))| child.as_ref() == name) .map(|(idx, (_, inode))| (idx + 2, inode.clone())) } } @@ -344,7 +357,7 @@ impl<'a> From<&'a str> for Str256 { s.len() }; inner[0..len].copy_from_slice(&s.as_bytes()[0..len]); - Str256(inner) + Self(inner) } } @@ -373,7 +386,12 @@ impl RamInode { fn new_file(fs: &Arc, mode: InodeMode) -> Arc { Arc::new_cyclic(|weak_self| { - let inode = RamInode(RwLock::new(Inode_::new_file(fs.alloc_id(), mode, &fs.sb()))); + let inode = RamInode(RwLock::new(Inode_::new_file( + fs.alloc_id(), + mode, + &fs.sb(), + weak_self.clone(), + ))); inode.0.write().fs = Arc::downgrade(fs); inode.0.write().this = weak_self.clone(); inode @@ -432,18 +450,65 @@ impl Inode for RamInode { Ok(()) } - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + fn page_cache(&self) -> Option> { + self.0 + .read() + .inner + .as_file() + .map(|page_cache| page_cache.pages()) + } + + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { if let Some(device) = self.0.read().inner.as_device() { return device.read(buf); } - return_errno_with_message!(Errno::EOPNOTSUPP, "direct read is not supported"); + + let self_inode = self.0.read(); + let Some(page_cache) = self_inode.inner.as_file() else { + return_errno_with_message!(Errno::EISDIR, "read is not supported"); + }; + let (offset, read_len) = { + let file_len = self_inode.metadata.size; + let start = file_len.min(offset); + let end = file_len.min(offset + buf.len()); + (start, end - start) + }; + page_cache + .pages() + .read_bytes(offset, &mut buf[..read_len])?; + Ok(read_len) } - fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + self.read_at(offset, buf) + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { if let Some(device) = self.0.read().inner.as_device() { return device.write(buf); } - return_errno_with_message!(Errno::EOPNOTSUPP, "direct write is not supported"); + + let self_inode = self.0.read(); + let Some(page_cache) = self_inode.inner.as_file() else { + return_errno_with_message!(Errno::EISDIR, "write is not supported"); + }; + let file_len = self_inode.metadata.size; + let new_len = offset + buf.len(); + let should_expand_len = new_len > file_len; + if should_expand_len { + page_cache.pages().resize(new_len)?; + } + page_cache.pages().write_bytes(offset, buf)?; + if should_expand_len { + // Turn the read guard into a write guard without releasing the lock. + let mut self_inode = self_inode.upgrade(); + self_inode.resize(new_len); + } + Ok(buf.len()) + } + + fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + self.write_at(offset, buf) } fn len(&self) -> usize { @@ -470,6 +535,14 @@ impl Inode for RamInode { self.0.write().metadata.mtime = time; } + fn type_(&self) -> InodeType { + self.0.read().metadata.type_ + } + + fn mode(&self) -> InodeMode { + self.0.read().metadata.mode + } + fn set_mode(&self, mode: InodeMode) { self.0.write().metadata.mode = mode; } @@ -483,6 +556,10 @@ impl Inode for RamInode { if self.0.read().metadata.type_ != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "self is not dir"); } + if name.len() > NAME_MAX { + return_errno!(Errno::ENAMETOOLONG); + } + let mut self_inode = self.0.write(); if self_inode.inner.as_direntry().unwrap().contains_entry(name) { return_errno_with_message!(Errno::EEXIST, "entry exists"); @@ -501,6 +578,10 @@ impl Inode for RamInode { if self.0.read().metadata.type_ != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "self is not dir"); } + if name.len() > NAME_MAX { + return_errno!(Errno::ENAMETOOLONG); + } + let mut self_inode = self.0.write(); if self_inode.inner.as_direntry().unwrap().contains_entry(name) { return_errno_with_message!(Errno::EEXIST, "entry exists"); @@ -512,7 +593,7 @@ impl Inode for RamInode { InodeType::Socket => RamInode::new_socket(&fs, mode), InodeType::Dir => { let dir_inode = RamInode::new_dir(&fs, mode, &self_inode.this); - self_inode.metadata.nlinks += 1; + self_inode.inc_nlinks(); dir_inode } _ => { @@ -545,6 +626,9 @@ impl Inode for RamInode { if self.0.read().metadata.type_ != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "self is not dir"); } + if !Arc::ptr_eq(&self.fs(), &old.fs()) { + return_errno_with_message!(Errno::EXDEV, "not same fs"); + } let old = old .downcast_ref::() .ok_or(Error::new(Errno::EXDEV))?; @@ -563,7 +647,7 @@ impl Inode for RamInode { .append_entry(name, old.0.read().this.upgrade().unwrap()); self_inode.inc_size(); drop(self_inode); - old.0.write().metadata.nlinks += 1; + old.0.write().inc_nlinks(); Ok(()) } @@ -583,7 +667,7 @@ impl Inode for RamInode { self_dir.remove_entry(idx); self_inode.dec_size(); drop(self_inode); - target.0.write().metadata.nlinks -= 1; + target.0.write().dec_nlinks(); Ok(()) } @@ -612,9 +696,11 @@ impl Inode for RamInode { } self_dir.remove_entry(idx); self_inode.dec_size(); - self_inode.metadata.nlinks -= 1; + self_inode.dec_nlinks(); drop(self_inode); - target.0.write().metadata.nlinks -= 2; + let mut target_inode = self.0.write(); + target_inode.dec_nlinks(); + target_inode.dec_nlinks(); Ok(()) } @@ -638,6 +724,9 @@ impl Inode for RamInode { if self.0.read().metadata.type_ != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "self is not dir"); } + if !Arc::ptr_eq(&self.fs(), &target.fs()) { + return_errno_with_message!(Errno::EXDEV, "not same fs"); + } let target = target .downcast_ref::() .ok_or(Error::new(Errno::EXDEV))?; @@ -703,8 +792,8 @@ impl Inode for RamInode { self_inode.dec_size(); target_inode.inc_size(); if src_inode.0.read().metadata.type_ == InodeType::Dir { - self_inode.metadata.nlinks -= 1; - target_inode.metadata.nlinks += 1; + self_inode.dec_nlinks(); + target_inode.inc_nlinks(); } drop(self_inode); drop(target_inode); @@ -736,7 +825,7 @@ impl Inode for RamInode { } let mut self_inode = self.0.write(); let link = self_inode.inner.as_symlink_mut().unwrap(); - *link = Str256::from(target); + *link = String::from(target); // Symlink's metadata.blocks should be 0, so just set the size. self_inode.metadata.size = target.len(); Ok(()) diff --git a/services/libs/jinux-std/src/fs/ramfs/mod.rs b/services/libs/jinux-std/src/fs/ramfs/mod.rs index 9760fd5f9..9bf41b31c 100644 --- a/services/libs/jinux-std/src/fs/ramfs/mod.rs +++ b/services/libs/jinux-std/src/fs/ramfs/mod.rs @@ -7,3 +7,4 @@ mod fs; const RAMFS_MAGIC: u64 = 0x0102_1994; const BLOCK_SIZE: usize = 4096; const ROOT_INO: usize = 1; +const NAME_MAX: usize = 255; diff --git a/services/libs/jinux-std/src/fs/rootfs.rs b/services/libs/jinux-std/src/fs/rootfs.rs index 327da0d95..13f18d10e 100644 --- a/services/libs/jinux-std/src/fs/rootfs.rs +++ b/services/libs/jinux-std/src/fs/rootfs.rs @@ -12,7 +12,7 @@ use spin::Once; /// Unpack and prepare the rootfs from the initramfs CPIO buffer. pub fn init(initramfs_buf: &[u8]) -> Result<()> { - init_root_mount()?; + init_root_mount(); println!("[kernel] unpacking the initramfs.cpio.gz to rootfs ..."); let fs = FsResolver::new(); @@ -52,7 +52,7 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { match metadata.file_type() { FileType::File => { let dentry = parent.create(name, InodeType::File, mode)?; - entry.read_all(dentry.vnode().writer(0))?; + entry.read_all(dentry.inode().writer(0))?; } FileType::Dir => { let _ = parent.create(name, InodeType::Dir, mode)?; @@ -64,7 +64,7 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { entry.read_all(&mut link_data)?; core::str::from_utf8(&link_data)?.to_string() }; - dentry.vnode().write_link(&link_content)?; + dentry.inode().write_link(&link_content)?; } type_ => { panic!("unsupported file type = {:?} in initramfs", type_); @@ -76,7 +76,7 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { proc_dentry.mount(ProcFS::new())?; // Mount DevFS let dev_dentry = fs.lookup(&FsPath::try_from("/dev")?)?; - dev_dentry.mount(RamFS::new(false))?; + dev_dentry.mount(RamFS::new())?; println!("[kernel] rootfs is ready"); Ok(()) @@ -84,14 +84,11 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { static ROOT_MOUNT: Once> = Once::new(); -fn init_root_mount() -> Result<()> { - ROOT_MOUNT.try_call_once(|| -> Result> { - let rootfs = RamFS::new(true); - let root_mount = MountNode::new_root(rootfs)?; - Ok(root_mount) - })?; - - Ok(()) +fn init_root_mount() { + ROOT_MOUNT.call_once(|| -> Arc { + let rootfs = RamFS::new(); + MountNode::new_root(rootfs) + }); } pub fn root_mount() -> &'static Arc { diff --git a/services/libs/jinux-std/src/fs/utils/dentry.rs b/services/libs/jinux-std/src/fs/utils/dentry.rs index 7d2d7d95a..4e0093d24 100644 --- a/services/libs/jinux-std/src/fs/utils/dentry.rs +++ b/services/libs/jinux-std/src/fs/utils/dentry.rs @@ -5,7 +5,7 @@ use alloc::string::String; use core::sync::atomic::{AtomicU32, Ordering}; use core::time::Duration; -use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, Vnode, NAME_MAX}; +use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX}; lazy_static! { static ref DCACHE: Mutex>> = Mutex::new(BTreeMap::new()); @@ -13,7 +13,7 @@ lazy_static! { /// The dentry cache to accelerate path lookup pub struct Dentry { - vnode: Vnode, + inode: Arc, name_and_parent: RwLock)>>, this: Weak, children: Mutex, @@ -22,21 +22,21 @@ pub struct Dentry { } impl Dentry { - /// Create a new root dentry with the giving vnode and mount node. + /// Create a new root dentry with the giving inode and mount node. /// /// It is been created during the construction of MountNode struct. The MountNode /// struct holds an arc reference to this root dentry, while this dentry holds a /// weak reference to the MountNode struct. - pub(super) fn new_root(vnode: Vnode, mount: Weak) -> Arc { - let root = Self::new(vnode, DentryOptions::Root(mount)); + pub(super) fn new_root(inode: Arc, mount: Weak) -> Arc { + let root = Self::new(inode, DentryOptions::Root(mount)); DCACHE.lock().insert(root.key(), root.clone()); root } /// Internal constructor. - fn new(vnode: Vnode, options: DentryOptions) -> Arc { + fn new(inode: Arc, options: DentryOptions) -> Arc { Arc::new_cyclic(|weak_self| Self { - vnode, + inode, mount_node: match &options { DentryOptions::Root(mount) => mount.clone(), DentryOptions::Leaf(name_and_parent) => name_and_parent.1.mount_node.clone(), @@ -129,9 +129,9 @@ impl Dentry { DentryKey::new(self) } - /// Get the vnode. - pub fn vnode(&self) -> &Vnode { - &self.vnode + /// Get the inode. + pub fn inode(&self) -> &Arc { + &self.inode } /// Get the DentryFlags. @@ -164,13 +164,9 @@ impl Dentry { self.mount_node.upgrade().unwrap() } - pub fn inode(&self) -> Weak { - self.vnode.inode() - } - /// Create a dentry by making inode. pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut children = self.children.lock(); @@ -179,9 +175,9 @@ impl Dentry { } let child = { - let vnode = self.vnode.create(name, type_, mode)?; + let inode = self.inode.create(name, type_, mode)?; let dentry = Self::new( - vnode, + inode, DentryOptions::Leaf((String::from(name), self.this())), ); children.insert_dentry(&dentry); @@ -192,7 +188,7 @@ impl Dentry { /// Create a dentry by making a device inode. pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc) -> Result> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut children = self.children.lock(); @@ -201,9 +197,9 @@ impl Dentry { } let child = { - let vnode = self.vnode.mknod(name, mode, device)?; + let inode = self.inode.mknod(name, mode, device)?; let dentry = Self::new( - vnode, + inode, DentryOptions::Leaf((String::from(name), self.this())), ); children.insert_dentry(&dentry); @@ -214,10 +210,10 @@ impl Dentry { /// Lookup a dentry. pub fn lookup(&self, name: &str) -> Result> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } - if !self.vnode.inode_mode().is_executable() { + if !self.inode.mode().is_executable() { return_errno!(Errno::EACCES); } if name.len() > NAME_MAX { @@ -232,9 +228,9 @@ impl Dentry { match children.find_dentry(name) { Some(dentry) => dentry.overlaid_dentry(), None => { - let vnode = self.vnode.lookup(name)?; + let inode = self.inode.lookup(name)?; let dentry = Self::new( - vnode, + inode, DentryOptions::Leaf((String::from(name), self.this())), ); children.insert_dentry(&dentry); @@ -248,7 +244,7 @@ impl Dentry { /// Link a new name for the dentry by linking inode. pub fn link(&self, old: &Arc, name: &str) -> Result<()> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut children = self.children.lock(); @@ -258,10 +254,10 @@ impl Dentry { if !Arc::ptr_eq(&old.mount_node(), &self.mount_node()) { return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); } - let old_vnode = old.vnode(); - self.vnode.link(old_vnode, name)?; + let old_inode = old.inode(); + self.inode.link(old_inode, name)?; let dentry = Self::new( - old_vnode.clone(), + old_inode.clone(), DentryOptions::Leaf((String::from(name), self.this())), ); children.insert_dentry(&dentry); @@ -270,51 +266,34 @@ impl Dentry { /// Delete a dentry by unlinking inode. pub fn unlink(&self, name: &str) -> Result<()> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut children = self.children.lock(); let _ = children.find_dentry_with_checking_mountpoint(name)?; - self.vnode.unlink(name)?; + self.inode.unlink(name)?; children.delete_dentry(name); Ok(()) } /// Delete a directory dentry by rmdiring inode. pub fn rmdir(&self, name: &str) -> Result<()> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut children = self.children.lock(); let _ = children.find_dentry_with_checking_mountpoint(name)?; - self.vnode.rmdir(name)?; + self.inode.rmdir(name)?; children.delete_dentry(name); Ok(()) } - /// Read symbolic link. - pub fn read_link(&self) -> Result { - if self.vnode.inode_type() != InodeType::SymLink { - return_errno!(Errno::EINVAL); - } - self.vnode.read_link() - } - - /// Write symbolic 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) - } - /// Rename a dentry to the new dentry by renaming inode. 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_type() != InodeType::Dir || new_dir.vnode.inode_type() != InodeType::Dir - { + if self.inode.type_() != InodeType::Dir || new_dir.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -326,7 +305,7 @@ impl Dentry { let mut children = self.children.lock(); let old_dentry = children.find_dentry_with_checking_mountpoint(old_name)?; let _ = children.find_dentry_with_checking_mountpoint(new_name)?; - self.vnode.rename(old_name, &self.vnode, new_name)?; + self.inode.rename(old_name, &self.inode, new_name)?; match old_dentry.as_ref() { Some(dentry) => { children.delete_dentry(old_name); @@ -346,7 +325,7 @@ impl Dentry { write_lock_children_on_two_dentries(self, new_dir); let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?; let _ = new_dir_children.find_dentry_with_checking_mountpoint(new_name)?; - self.vnode.rename(old_name, &new_dir.vnode, new_name)?; + self.inode.rename(old_name, &new_dir.inode, new_name)?; match old_dentry.as_ref() { Some(dentry) => { self_children.delete_dentry(old_name); @@ -369,7 +348,7 @@ impl Dentry { /// /// Return the mounted child mount. pub fn mount(&self, fs: Arc) -> Result> { - if self.vnode.inode_type() != InodeType::Dir { + if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } if self.effective_parent().is_none() { @@ -401,52 +380,52 @@ impl Dentry { /// Get the filesystem the inode belongs to pub fn fs(&self) -> Arc { - self.vnode.fs() + self.inode.fs() } /// Get the inode metadata pub fn inode_metadata(&self) -> Metadata { - self.vnode.metadata() + self.inode.metadata() } /// Get the inode type pub fn inode_type(&self) -> InodeType { - self.vnode.inode_type() + self.inode.type_() } /// Get the inode permission mode pub fn inode_mode(&self) -> InodeMode { - self.vnode.inode_mode() + self.inode.mode() } /// Set the inode permission mode pub fn set_inode_mode(&self, mode: InodeMode) { - self.vnode.set_inode_mode(mode) + self.inode.set_mode(mode) } /// Get the inode length pub fn inode_len(&self) -> usize { - self.vnode.len() + self.inode.len() } /// Get the access timestamp pub fn atime(&self) -> Duration { - self.vnode.atime() + self.inode.atime() } /// Set the access timestamp pub fn set_atime(&self, time: Duration) { - self.vnode.set_atime(time) + self.inode.set_atime(time) } /// Get the modified timestamp pub fn mtime(&self) -> Duration { - self.vnode.mtime() + self.inode.mtime() } /// Set the modified timestamp pub fn set_mtime(&self, time: Duration) { - self.vnode.set_mtime(time) + self.inode.set_mtime(time) } /// Get the absolute path. @@ -482,7 +461,7 @@ impl Debug for Dentry { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Dentry") .field("abs_path", &self.abs_path()) - .field("vnode", &self.vnode) + .field("inode", &self.inode) .field("flags", &self.flags()) .finish() } @@ -537,7 +516,7 @@ impl Children { pub fn insert_dentry(&mut self, dentry: &Arc) { // Do not cache it in DCACHE and children if is not cacheable. // When we look up it from the parent, it will always be newly created. - if !dentry.vnode().is_dentry_cacheable() { + if !dentry.inode().is_dentry_cacheable() { return; } diff --git a/services/libs/jinux-std/src/fs/utils/fs.rs b/services/libs/jinux-std/src/fs/utils/fs.rs index e950c00ec..f06a5d869 100644 --- a/services/libs/jinux-std/src/fs/utils/fs.rs +++ b/services/libs/jinux-std/src/fs/utils/fs.rs @@ -1,7 +1,3 @@ -use alloc::sync::Arc; -use bitflags::bitflags; -use core::any::Any; - use super::Inode; use crate::prelude::*; @@ -40,8 +36,6 @@ impl SuperBlock { bitflags! { pub struct FsFlags: u32 { - /// Disable page cache. - const NO_PAGECACHE = 1 << 0; /// Dentry cannot be evicted. const DENTRY_UNEVICTABLE = 1 << 1; } diff --git a/services/libs/jinux-std/src/fs/utils/inode.rs b/services/libs/jinux-std/src/fs/utils/inode.rs index a27c62131..5a0132a4b 100644 --- a/services/libs/jinux-std/src/fs/utils/inode.rs +++ b/services/libs/jinux-std/src/fs/utils/inode.rs @@ -1,18 +1,17 @@ -use alloc::string::String; -use alloc::sync::Arc; -use bitflags::bitflags; -use core::any::Any; use core::time::Duration; +use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write}; use jinux_frame::vm::VmFrame; +use jinux_rights::Full; use super::{DirentVisitor, FileSystem, IoctlCmd, SuperBlock}; use crate::events::IoEvents; use crate::fs::device::{Device, DeviceType}; use crate::prelude::*; use crate::process::signal::Poller; +use crate::vm::vmo::Vmo; #[repr(u32)] -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromInt)] pub enum InodeType { NamedPipe = 0o010000, CharDevice = 0o020000, @@ -236,6 +235,12 @@ pub trait Inode: Any + Sync + Send { fn metadata(&self) -> Metadata; + fn type_(&self) -> InodeType; + + fn mode(&self) -> InodeMode; + + fn set_mode(&self, mode: InodeMode); + fn atime(&self) -> Duration; fn set_atime(&self, time: Duration); @@ -244,8 +249,6 @@ pub trait Inode: Any + Sync + Send { fn set_mtime(&self, time: Duration); - fn set_mode(&self, mode: InodeMode); - fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> { Err(Error::new(Errno::EISDIR)) } @@ -254,14 +257,26 @@ pub trait Inode: Any + Sync + Send { Err(Error::new(Errno::EISDIR)) } + fn page_cache(&self) -> Option> { + None + } + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { Err(Error::new(Errno::EISDIR)) } + fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result { + Err(Error::new(Errno::EISDIR)) + } + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { Err(Error::new(Errno::EISDIR)) } + fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { + Err(Error::new(Errno::EISDIR)) + } + fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { Err(Error::new(Errno::ENOTDIR)) } @@ -343,6 +358,59 @@ impl dyn Inode { pub fn downcast_ref(&self) -> Option<&T> { (self as &dyn Any).downcast_ref::() } + + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + if !self.type_().support_read() { + return_errno!(Errno::EISDIR); + } + + let file_len = self.len(); + if buf.len() < file_len { + buf.resize(file_len, 0); + } + self.read_at(0, &mut buf[..file_len]) + } + + pub fn read_direct_to_end(&self, buf: &mut Vec) -> Result { + if !self.type_().support_read() { + return_errno!(Errno::EISDIR); + } + + let file_len = self.len(); + if buf.len() < file_len { + buf.resize(file_len, 0); + } + self.read_direct_at(0, &mut buf[..file_len]) + } + + pub fn writer(&self, from_offset: usize) -> InodeWriter { + InodeWriter { + inner: self, + offset: from_offset, + } + } +} + +pub struct InodeWriter<'a> { + inner: &'a dyn Inode, + offset: usize, +} + +impl<'a> Write for InodeWriter<'a> { + #[inline] + fn write(&mut self, buf: &[u8]) -> IoResult { + let write_len = self + .inner + .write_at(self.offset, buf) + .map_err(|_| IoError::new(IoErrorKind::WriteZero, "failed to write buffer"))?; + self.offset += write_len; + Ok(write_len) + } + + #[inline] + fn flush(&mut self) -> IoResult<()> { + Ok(()) + } } impl Debug for dyn Inode { diff --git a/services/libs/jinux-std/src/fs/utils/mod.rs b/services/libs/jinux-std/src/fs/utils/mod.rs index b8f9e9839..441ed6674 100644 --- a/services/libs/jinux-std/src/fs/utils/mod.rs +++ b/services/libs/jinux-std/src/fs/utils/mod.rs @@ -13,7 +13,6 @@ pub use ioctl::IoctlCmd; pub use mount::MountNode; pub use page_cache::PageCache; pub use status_flags::StatusFlags; -pub use vnode::{Vnode, VnodeWriter}; mod access_mode; mod channel; @@ -28,7 +27,6 @@ mod ioctl; mod mount; mod page_cache; mod status_flags; -mod vnode; #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum SeekFrom { diff --git a/services/libs/jinux-std/src/fs/utils/mount.rs b/services/libs/jinux-std/src/fs/utils/mount.rs index 067427fa7..1c598eedb 100644 --- a/services/libs/jinux-std/src/fs/utils/mount.rs +++ b/services/libs/jinux-std/src/fs/utils/mount.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -use super::{Dentry, DentryKey, FileSystem, InodeType, Vnode}; +use super::{Dentry, DentryKey, FileSystem, InodeType}; /// The MountNode can form a mount tree to maintain the mount information. pub struct MountNode { @@ -25,22 +25,21 @@ impl MountNode { /// /// It is allowed to create a mount node even if the fs has been provided to another /// mount node. It is the fs's responsibility to ensure the data consistency. - pub fn new_root(fs: Arc) -> Result> { + pub fn new_root(fs: Arc) -> Arc { Self::new(fs, None) } /// The internal constructor. /// /// Root mount node has no mountpoint which other mount nodes must have mountpoint. - fn new(fs: Arc, mountpoint: Option>) -> Result> { - let vnode = Vnode::new(fs.root_inode())?; - Ok(Arc::new_cyclic(|weak_self| Self { - root_dentry: Dentry::new_root(vnode, weak_self.clone()), + fn new(fs: Arc, mountpoint: Option>) -> Arc { + Arc::new_cyclic(|weak_self| Self { + root_dentry: Dentry::new_root(fs.root_inode(), weak_self.clone()), mountpoint_dentry: mountpoint, children: Mutex::new(BTreeMap::new()), fs, this: weak_self.clone(), - })) + }) } /// Mount an fs on the mountpoint, it will create a new child mount node. @@ -63,7 +62,7 @@ impl MountNode { } let key = mountpoint.key(); - let child_mount = Self::new(fs, Some(mountpoint.clone()))?; + let child_mount = Self::new(fs, Some(mountpoint.clone())); self.children.lock().insert(key, child_mount.clone()); Ok(child_mount) } diff --git a/services/libs/jinux-std/src/fs/utils/page_cache.rs b/services/libs/jinux-std/src/fs/utils/page_cache.rs index 694c333db..1251c5bdc 100644 --- a/services/libs/jinux-std/src/fs/utils/page_cache.rs +++ b/services/libs/jinux-std/src/fs/utils/page_cache.rs @@ -1,6 +1,6 @@ use super::Inode; use crate::prelude::*; -use crate::vm::vmo::{Pager, Vmo, VmoFlags, VmoOptions}; +use crate::vm::vmo::{get_page_idx_range, Pager, Vmo, VmoFlags, VmoOptions}; use jinux_rights::Full; use core::ops::Range; @@ -13,24 +13,40 @@ pub struct PageCache { } impl PageCache { - pub fn new(inode: &Arc) -> Result { - let manager = Arc::new(PageCacheManager::new(Arc::downgrade(inode))); - let pages = VmoOptions::::new(inode.len()) + /// Creates an empty size page cache associated with a new inode. + pub fn new(backed_inode: Weak) -> Result { + let manager = Arc::new(PageCacheManager::new(backed_inode)); + let pages = VmoOptions::::new(0) .flags(VmoFlags::RESIZABLE) .pager(manager.clone()) .alloc()?; Ok(Self { pages, manager }) } - pub fn pages(&self) -> &Vmo { - &self.pages + /// Creates a page cache associated with an existing inode. + /// + /// The `capacity` is the initial cache size required by the inode. + /// It is usually used the same size as the inode. + pub fn with_capacity(capacity: usize, backed_inode: Weak) -> Result { + let manager = Arc::new(PageCacheManager::new(backed_inode)); + let pages = VmoOptions::::new(capacity) + .flags(VmoFlags::RESIZABLE) + .pager(manager.clone()) + .alloc()?; + Ok(Self { pages, manager }) + } + + /// Returns the Vmo object backed by inode. + // TODO: The capability is too high,restrict it to eliminate the possibility of misuse. + // For example, the `resize` api should be forbidded. + pub fn pages(&self) -> Vmo { + self.pages.dup().unwrap() } /// Evict the data within a specified range from the page cache and persist /// them to the disk. - pub fn evict_range(&self, range: Range) { - // TODO: Implement this method. - warn!("pagecache: evict_range is not implemented"); + pub fn evict_range(&self, range: Range) -> Result<()> { + self.manager.evict_range(range) } } @@ -49,12 +65,31 @@ struct PageCacheManager { } impl PageCacheManager { - pub fn new(inode: Weak) -> Self { + pub fn new(backed_inode: Weak) -> Self { Self { pages: Mutex::new(LruCache::unbounded()), - backed_inode: inode, + backed_inode, } } + + pub fn evict_range(&self, range: Range) -> Result<()> { + let page_idx_range = get_page_idx_range(&range); + let mut pages = self.pages.lock(); + for page_idx in page_idx_range { + if let Some(page) = pages.get_mut(&page_idx) { + if let PageState::Dirty = page.state() { + self.backed_inode + .upgrade() + .unwrap() + .write_page(page_idx, page.frame())?; + page.set_state(PageState::UpToDate); + } + } else { + warn!("page {} is not in page cache, do nothing", page_idx); + } + } + Ok(()) + } } impl Debug for PageCacheManager { @@ -70,20 +105,18 @@ impl Pager for PageCacheManager { let page_idx = offset / PAGE_SIZE; let mut pages = self.pages.lock(); let frame = if let Some(page) = pages.get(&page_idx) { - page.frame() + page.frame().clone() } else { - let page = if offset < self.backed_inode.upgrade().unwrap().metadata().size { - let mut page = Page::alloc_zero()?; - self.backed_inode - .upgrade() - .unwrap() - .read_page(page_idx, &page.frame())?; + let backed_inode = self.backed_inode.upgrade().unwrap(); + let page = if offset < backed_inode.len() { + let mut page = Page::alloc()?; + backed_inode.read_page(page_idx, page.frame())?; page.set_state(PageState::UpToDate); page } else { Page::alloc_zero()? }; - let frame = page.frame(); + let frame = page.frame().clone(); pages.put(page_idx, page); frame }; @@ -110,7 +143,7 @@ impl Pager for PageCacheManager { self.backed_inode .upgrade() .unwrap() - .write_page(page_idx, &page.frame())? + .write_page(page_idx, page.frame())? } } else { warn!("page {} is not in page cache, do nothing", page_idx); @@ -151,8 +184,8 @@ impl Page { }) } - pub fn frame(&self) -> VmFrame { - self.frame.clone() + pub fn frame(&self) -> &VmFrame { + &self.frame } pub fn state(&self) -> &PageState { diff --git a/services/libs/jinux-std/src/fs/utils/vnode.rs b/services/libs/jinux-std/src/fs/utils/vnode.rs deleted file mode 100644 index c064445e0..000000000 --- a/services/libs/jinux-std/src/fs/utils/vnode.rs +++ /dev/null @@ -1,300 +0,0 @@ -use super::{ - DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, PageCache, -}; -use crate::events::IoEvents; -use crate::fs::device::Device; -use crate::prelude::*; -use crate::process::signal::Poller; -use crate::vm::vmo::Vmo; - -use alloc::string::String; -use core::time::Duration; -use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write}; -use jinux_frame::vm::VmIo; -use jinux_rights::Full; - -/// 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, - page_cache: Option, -} - -impl Vnode { - pub fn page_cache(&self) -> Option> { - self.inner - .read() - .page_cache - .as_ref() - .map(|page_chche| page_chche.pages().dup().unwrap()) - } - - pub fn new(inode: Arc) -> Result { - let page_cache = if inode.fs().flags().contains(FsFlags::NO_PAGECACHE) { - None - } else { - Some(PageCache::new(&inode)?) - }; - Ok(Self { - inner: Arc::new(RwLock::new(Inner { inode, page_cache })), - }) - } - - pub fn write_at(&self, offset: usize, buf: &[u8]) -> Result { - let type_ = self.inode_type(); - if !type_.support_write() { - return_errno!(Errno::EINVAL); - } - let inner = self.inner.write(); - match &inner.page_cache { - None => inner.inode.write_at(offset, buf), - Some(page_cache) => { - let file_len = inner.inode.len(); - let should_expand_len = offset + buf.len() > file_len; - if should_expand_len { - page_cache.pages().resize(offset + buf.len())?; - } - page_cache.pages().write_bytes(offset, buf)?; - if should_expand_len { - inner.inode.resize(offset + buf.len()); - } - Ok(buf.len()) - } - } - } - - pub fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result { - let type_ = self.inode_type(); - if !type_.support_write() { - return_errno!(Errno::EINVAL); - } - let inner = self.inner.write(); - if let Some(page_cache) = &inner.page_cache { - page_cache.evict_range(offset..offset + buf.len()); - } - inner.inode.write_at(offset, buf) - } - - pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { - let type_ = self.inode_type(); - if !type_.support_read() { - return_errno!(Errno::EISDIR); - } - let inner = self.inner.read(); - match &inner.page_cache { - None => inner.inode.read_at(offset, buf), - Some(page_cache) => { - 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) - }; - page_cache - .pages() - .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_.support_read() { - return_errno!(Errno::EISDIR); - } - let inner = self.inner.read(); - if let Some(page_cache) = &inner.page_cache { - page_cache.evict_range(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_.support_read() { - 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); - } - match &inner.page_cache { - None => inner.inode.read_at(0, &mut buf[..file_len]), - Some(page_cache) => { - page_cache.pages().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_.support_read() { - 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); - } - if let Some(page_cache) = &inner.page_cache { - page_cache.evict_range(0..file_len); - } - - inner.inode.read_at(0, &mut buf[..file_len]) - } - - pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result { - let inode = self.inner.read().inode.create(name, type_, mode)?; - Self::new(inode) - } - - pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc) -> Result { - let inode = self.inner.read().inode.mknod(name, mode, device)?; - 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_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result { - self.inner.read().inode.readdir_at(offset, visitor) - } - - pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents { - let inode = self.inner.read().inode.clone(); - inode.poll(mask, poller) - } - - pub fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { - let inode = self.inner.read().inode.clone(); - inode.ioctl(cmd, arg) - } - - pub fn fs(&self) -> Arc { - self.inner.read().inode.fs() - } - - pub fn metadata(&self) -> Metadata { - self.inner.read().inode.metadata() - } - - pub fn inode(&self) -> Weak { - let inner = self.inner.read(); - Arc::downgrade(&inner.inode) - } - - 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 set_inode_mode(&self, mode: InodeMode) { - self.inner.read().inode.set_mode(mode) - } - - pub fn len(&self) -> usize { - self.inner.read().inode.len() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn atime(&self) -> Duration { - self.inner.read().inode.atime() - } - - pub fn set_atime(&self, time: Duration) { - self.inner.read().inode.set_atime(time) - } - - pub fn mtime(&self) -> Duration { - self.inner.read().inode.mtime() - } - - pub fn set_mtime(&self, time: Duration) { - self.inner.read().inode.set_mtime(time) - } - - pub fn is_dentry_cacheable(&self) -> bool { - self.inner.read().inode.is_dentry_cacheable() - } - - pub fn writer(&self, from_offset: usize) -> VnodeWriter { - VnodeWriter { - inner: self, - offset: from_offset, - } - } -} - -impl Debug for Vnode { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.debug_struct("Vnode") - .field("inode", &self.inner.read().inode) - .field("page_cache", &self.inner.read().page_cache) - .finish() - } -} - -pub struct VnodeWriter<'a> { - inner: &'a Vnode, - offset: usize, -} - -impl<'a> Write for VnodeWriter<'a> { - #[inline] - fn write(&mut self, buf: &[u8]) -> IoResult { - let write_len = self - .inner - .write_at(self.offset, buf) - .map_err(|_| IoError::new(IoErrorKind::WriteZero, "failed to write buffer"))?; - self.offset += write_len; - Ok(write_len) - } - - #[inline] - fn flush(&mut self) -> IoResult<()> { - Ok(()) - } -} diff --git a/services/libs/jinux-std/src/net/socket/unix/addr.rs b/services/libs/jinux-std/src/net/socket/unix/addr.rs index 313b57167..825e5d021 100644 --- a/services/libs/jinux-std/src/net/socket/unix/addr.rs +++ b/services/libs/jinux-std/src/net/socket/unix/addr.rs @@ -18,15 +18,7 @@ impl PartialEq for UnixSocketAddrBound { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Abstract(l0), Self::Abstract(r0)) => l0 == r0, - (Self::Path(l0), Self::Path(r0)) => { - let Some(linode) = l0.inode().upgrade() else { - return false; - }; - let Some(rinode) = r0.inode().upgrade() else { - return false; - }; - Arc::ptr_eq(&linode, &rinode) - } + (Self::Path(l0), Self::Path(r0)) => Arc::ptr_eq(l0.inode(), r0.inode()), _ => false, } } diff --git a/services/libs/jinux-std/src/net/socket/unix/stream/listener.rs b/services/libs/jinux-std/src/net/socket/unix/stream/listener.rs index d143c3b0d..c406eb52c 100644 --- a/services/libs/jinux-std/src/net/socket/unix/stream/listener.rs +++ b/services/libs/jinux-std/src/net/socket/unix/stream/listener.rs @@ -203,8 +203,8 @@ impl Backlog { } fn create_keyable_inode(dentry: &Arc) -> KeyableWeak { - let inode = dentry.inode(); - KeyableWeak::from(inode) + let weak_inode = Arc::downgrade(dentry.inode()); + KeyableWeak::from(weak_inode) } pub(super) fn unregister_backlog(addr: &UnixSocketAddrBound) { diff --git a/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs b/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs index 750fbcbf6..7e3d6d9e9 100644 --- a/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs +++ b/services/libs/jinux-std/src/process/program_loader/elf/load_elf.rs @@ -69,8 +69,8 @@ fn lookup_and_parse_ldso( }; let ldso_elf = { let mut buf = Box::new([0u8; PAGE_SIZE]); - let vnode = ldso_file.vnode(); - vnode.read_at(0, &mut *buf)?; + let inode = ldso_file.inode(); + inode.read_at(0, &mut *buf)?; Elf::parse_elf(&*buf)? }; Ok((ldso_file, ldso_elf)) @@ -250,8 +250,8 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu let virtual_addr = program_header.virtual_addr as usize; debug_assert!(file_offset % PAGE_SIZE == virtual_addr % PAGE_SIZE); let page_cache_vmo = { - let vnode = elf_file.vnode(); - vnode.page_cache().ok_or(Error::with_message( + let inode = elf_file.inode(); + inode.page_cache().ok_or(Error::with_message( Errno::ENOENT, "executable has no page cache", ))? diff --git a/services/libs/jinux-std/src/process/program_loader/mod.rs b/services/libs/jinux-std/src/process/program_loader/mod.rs index 2544ccb12..3c4deea08 100644 --- a/services/libs/jinux-std/src/process/program_loader/mod.rs +++ b/services/libs/jinux-std/src/process/program_loader/mod.rs @@ -26,11 +26,11 @@ pub fn load_program_to_vm( recursion_limit: usize, ) -> Result<(String, ElfLoadInfo)> { let abs_path = elf_file.abs_path(); - let vnode = elf_file.vnode(); + let inode = elf_file.inode(); let file_header = { // read the first page of file header let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]); - vnode.read_at(0, &mut *file_header_buffer)?; + inode.read_at(0, &mut *file_header_buffer)?; file_header_buffer }; if let Some(mut new_argv) = parse_shebang_line(&*file_header)? { diff --git a/services/libs/jinux-std/src/syscall/mmap.rs b/services/libs/jinux-std/src/syscall/mmap.rs index ace8d0fd4..5b58fe917 100644 --- a/services/libs/jinux-std/src/syscall/mmap.rs +++ b/services/libs/jinux-std/src/syscall/mmap.rs @@ -102,8 +102,8 @@ fn mmap_filebacked_vmo( let page_cache_vmo = { let fs_resolver = current.fs().read(); let dentry = fs_resolver.lookup_from_fd(fd)?; - let vnode = dentry.vnode(); - vnode.page_cache().ok_or(Error::with_message( + let inode = dentry.inode(); + inode.page_cache().ok_or(Error::with_message( Errno::EBADF, "File does not have page cache", ))? diff --git a/services/libs/jinux-std/src/syscall/readlink.rs b/services/libs/jinux-std/src/syscall/readlink.rs index 455512887..dbba1dad8 100644 --- a/services/libs/jinux-std/src/syscall/readlink.rs +++ b/services/libs/jinux-std/src/syscall/readlink.rs @@ -32,7 +32,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.read_link()?; + let linkpath = dentry.inode().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/services/libs/jinux-std/src/syscall/symlink.rs b/services/libs/jinux-std/src/syscall/symlink.rs index b2b205eb4..c63a701bf 100644 --- a/services/libs/jinux-std/src/syscall/symlink.rs +++ b/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.write_link(&target)?; + new_dentry.inode().write_link(&target)?; Ok(SyscallReturn::Return(0)) }