diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index e3817af4c5..e45f213418 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -5,7 +5,7 @@ use rmm::PhysicalAddress; use crate::{ context::{ - file::{FileDescription, InternalFlags, LockedFileDescription}, + file::InternalFlags, memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan}, }, memory::{free_frames, used_frames, Frame, PAGE_SIZE}, @@ -19,7 +19,7 @@ use crate::paging::entry::EntryFlags; use crate::syscall::{ data::{Map, StatVfs}, error::*, - flag::{CallFlags, MapFlags}, + flag::MapFlags, usercopy::UserSliceWo, }; @@ -335,32 +335,4 @@ impl KernelScheme for MemoryScheme { Ok(()) } - fn kstdfscall( - &self, - id: usize, - _desc: Arc, - payload: UserSliceRw, - _flags: CallFlags, - metadata: &[u64], - token: &mut CleanLockToken, - ) -> Result { - use syscall::flag::StdFsCallKind::{self, *}; - let Some(raw_kind) = metadata.first().map(|v| *v as u8) else { - return Err(Error::new(EOPNOTSUPP)); - }; - let Some(kind) = StdFsCallKind::try_from_raw(raw_kind) else { - return Err(Error::new(EOPNOTSUPP)); - }; - - match kind { - Fstatvfs => { - if payload.len() != core::mem::size_of::() { - return Err(Error::new(EINVAL)); - } - self.kfstatvfs(id, UserSliceWo::new(payload.addr(), payload.len())?, token) - .map(|_| 0) - } - _ => Err(Error::new(EOPNOTSUPP)), - } - } } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 02a50e4b86..895b016889 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -19,9 +19,9 @@ use core::{ use hashbrown::hash_map::{DefaultHashBuilder, HashMap}; use spin::Once; use syscall::{ - data::{GlobalSchemes, NewFdParams}, + data::{GlobalSchemes, NewFdParams, StdFsCallMeta}, error::*, - CallFlags, EventFlags, MunmapFlags, + CallFlags, EventFlags, MunmapFlags, StdFsCallKind, }; use crate::{ @@ -675,10 +675,11 @@ pub trait KernelScheme: Send + Sync + 'static { fn kstdfscall( &self, id: usize, + kind: StdFsCallKind, desc: Arc, payload: UserSliceRw, flags: CallFlags, - metadata: &[u64], + metadata: StdFsCallMeta, token: &mut CleanLockToken, ) -> Result { Err(Error::new(EOPNOTSUPP)) @@ -704,6 +705,45 @@ pub trait KernelScheme: Send + Sync + 'static { ) -> Result { Err(Error::new(EOPNOTSUPP)) } + + fn translate_std_fs_call( + &self, + id: usize, + desc: Arc, + payload: UserSliceRw, + flags: CallFlags, + metadata: &[u64], + token: &mut CleanLockToken, + ) -> Result { + let &[kind, arg1, arg2, ..] = metadata else { + return Err(Error::new(EINVAL)); + }; + let Some(kind) = StdFsCallKind::try_from_raw(kind as u8) else { + return Err(Error::new(EOPNOTSUPP)); + }; + let metadata = StdFsCallMeta::new(kind, arg1, arg2); + use syscall::flag::StdFsCallKind::*; + match kind { + Fchmod => self.fchmod(id, metadata.arg1 as u16, token).map(|_| 0), + Getdents => self.getdents( + id, + payload.into_wo()?, + metadata.arg2 as u16, + metadata.arg1, + token, + ), + Fstat => self.kfstat(id, payload.into_wo()?, token).map(|_| 0), + Fstatvfs => self.kfstatvfs(id, payload.into_wo()?, token).map(|_| 0), + Fsync => self.fsync(id, token).map(|_| 0), + Ftruncate => self.ftruncate(id, metadata.arg1 as usize, token).map(|_| 0), + Futimens => self.kfutimens(id, payload.into_ro()?, token), + /* TODO: Support Fchown and Unlinkat using std_fs_call + Fchown => self.kstdfscall(id, kind, desc, payload, flags, metadata, token), + Unlinkat => self.kstdfscall(fd, kind, payload, metadata, &caller).map(|_| 0) + */ + _ => Err(Error::new(EOPNOTSUPP)), + } + } } #[derive(Debug)] diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 94012a2ce7..b80b456bcf 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -7,7 +7,7 @@ use slab::Slab; use syscall::{ schemev2::{Cqe, CqeOpcode, Opcode, Sqe, SqeFlags}, CallFlags, FmoveFdFlags, FobtainFdFlags, MunmapFlags, RecvFdFlags, SchemeSocketCall, - SendFdFlags, MAP_FIXED_NOREPLACE, + SendFdFlags, StdFsCallKind, MAP_FIXED_NOREPLACE, }; use crate::{ @@ -27,7 +27,7 @@ use crate::{ scheme::SchemeId, sync::{CleanLockToken, LockToken, Mutex, RwLock, WaitQueue, L1}, syscall::{ - data::Map, + data::{Map, StdFsCallMeta}, error::*, flag::{EventFlags, MapFlags, EVENT_READ, O_NONBLOCK, PROT_READ}, usercopy::{UserSlice, UserSliceRo, UserSliceRw, UserSliceWo}, @@ -1939,10 +1939,11 @@ impl KernelScheme for UserScheme { fn kstdfscall( &self, id: usize, + _kind: StdFsCallKind, desc: Arc, payload: UserSliceRw, _flags: CallFlags, - metadata: &[u64], + metadata: StdFsCallMeta, token: &mut CleanLockToken, ) -> Result { let inner = self.inner.clone(); @@ -2080,6 +2081,24 @@ impl KernelScheme for UserScheme { Ok(num_fds) } + fn translate_std_fs_call( + &self, + id: usize, + desc: Arc, + payload: UserSliceRw, + flags: CallFlags, + metadata: &[u64], + token: &mut CleanLockToken, + ) -> Result { + let &[kind, arg1, arg2, ..] = metadata else { + return Err(Error::new(EINVAL)); + }; + let Some(kind) = StdFsCallKind::try_from_raw(kind as u8) else { + return Err(Error::new(EOPNOTSUPP)); + }; + let metadata = StdFsCallMeta::new(kind, arg1, arg2); + self.kstdfscall(id, kind, desc, payload, flags, metadata, token) + } } trait Args: Copy { diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 1be232fda3..1a7f6e698e 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -303,7 +303,7 @@ fn call_normal( let scheme = scheme::get_scheme(token.token(), scheme_id)?; if flags.contains(CallFlags::STD_FS) { - scheme.kstdfscall(number, file.description, payload, flags, metadata, token) + scheme.translate_std_fs_call(number, file.description, payload, flags, metadata, token) } else { scheme.kcall(number, payload, flags, metadata, token) } diff --git a/src/syscall/usercopy.rs b/src/syscall/usercopy.rs index d4b3016fe8..83cdac1424 100644 --- a/src/syscall/usercopy.rs +++ b/src/syscall/usercopy.rs @@ -212,6 +212,12 @@ impl UserSliceRw { pub fn rw(base: usize, size: usize) -> Result { Self::new(base, size) } + pub fn into_ro(self) -> Result { + UserSliceRo::ro(self.base, self.len) + } + pub fn into_wo(self) -> Result { + UserSliceWo::wo(self.base, self.len) + } } fn is_kernel_mem(slice: &[u8]) -> bool {