From 27a3c752097d85bafac3f80588e6874a396d232d Mon Sep 17 00:00:00 2001 From: LI Qing Date: Tue, 14 Mar 2023 12:00:37 +0800 Subject: [PATCH] [libos] Refine the getdents syscall. --- deps/sefs | 2 +- src/libos/src/fs/file_ops/getdents.rs | 46 ++++++++++------------- src/libos/src/fs/hostfs.rs | 17 +++------ src/libos/src/fs/procfs/mod.rs | 12 +++--- src/libos/src/fs/procfs/pid/fd.rs | 16 ++------ src/libos/src/fs/procfs/pid/mod.rs | 16 ++------ src/libos/src/fs/procfs/proc_inode/mod.rs | 29 ++++++-------- 7 files changed, 51 insertions(+), 87 deletions(-) diff --git a/deps/sefs b/deps/sefs index 98196fb6..a771d5d3 160000 --- a/deps/sefs +++ b/deps/sefs @@ -1 +1 @@ -Subproject commit 98196fb62f64f0edeacc20d60c30aaaf4a290f70 +Subproject commit a771d5d37f2a21b02ee579bab85dc8e551d924e0 diff --git a/src/libos/src/fs/file_ops/getdents.rs b/src/libos/src/fs/file_ops/getdents.rs index a5a928b3..2c60f1bf 100644 --- a/src/libos/src/fs/file_ops/getdents.rs +++ b/src/libos/src/fs/file_ops/getdents.rs @@ -23,13 +23,13 @@ fn getdents_common(fd: FileDesc, buf: &mut [u8]) -> Result { return_errno!(ENOTDIR, ""); } let mut writer = DirentBufWriter::::new(buf); - let written_size = file_ref.iterate_entries(&mut writer)?; - Ok(written_size) + let written_len = file_ref.iterate_entries(&mut writer)?; + Ok(written_len) } struct DirentBufWriter<'a, T: Dirent> { buf: &'a mut [u8], - written_size: usize, + written_len: usize, phantom: PhantomData, } @@ -37,40 +37,34 @@ impl<'a, T: Dirent> DirentBufWriter<'a, T> { fn new(buf: &'a mut [u8]) -> Self { Self { buf, - written_size: 0, + written_len: 0, phantom: PhantomData, } } - - fn try_write(&mut self, name: &str, ino: u64, type_: FileType) -> Result { - let dirent: T = Dirent::new(name, ino, type_); - if self.buf.len() - self.written_size < dirent.rec_len() { - return_errno!(EINVAL, "the given buffer is too small"); - } - dirent.dump(&mut self.buf[self.written_size..], name, type_)?; - self.written_size += dirent.rec_len(); - Ok(dirent.rec_len()) - } } impl<'a, T: Dirent> DirentWriter for DirentBufWriter<'a, T> { - fn write_entry( - &mut self, - name: &str, - ino: u64, - type_: FileType, - ) -> rcore_fs::vfs::Result { - let written_len = self - .try_write(&name, ino, type_) + fn write_entry(&mut self, name: &str, ino: u64, type_: FileType) -> rcore_fs::vfs::Result<()> { + let dirent: T = Dirent::new(name, ino, type_); + if self.buf.len() - self.written_len < dirent.rec_len() { + return Err(FsError::InvalidParam); + } + dirent + .serialize(&mut self.buf[self.written_len..], name, type_) .map_err(|_| FsError::InvalidParam)?; - Ok(written_len) + self.written_len += dirent.rec_len(); + Ok(()) + } + + fn written_len(&self) -> usize { + self.written_len } } trait Dirent: Sync + Send { fn new(name: &str, ino: u64, type_: FileType) -> Self; fn rec_len(&self) -> usize; - fn dump(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()>; + fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()>; } /// Same with struct linux_dirent64 @@ -106,7 +100,7 @@ impl Dirent for LinuxDirent64 { self.rec_len as usize } - fn dump(&self, buf: &mut [u8], name: &str, _type_: FileType) -> Result<()> { + fn serialize(&self, buf: &mut [u8], name: &str, _type_: FileType) -> Result<()> { unsafe { let ptr = buf.as_mut_ptr() as *mut Self; ptr.write(*self); @@ -154,7 +148,7 @@ impl Dirent for LinuxDirent { self.rec_len as usize } - fn dump(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()> { + fn serialize(&self, buf: &mut [u8], name: &str, type_: FileType) -> Result<()> { unsafe { let ptr = buf.as_mut_ptr() as *mut Self; ptr.write(*self); diff --git a/src/libos/src/fs/hostfs.rs b/src/libos/src/fs/hostfs.rs index db055aaa..2da7c6ca 100644 --- a/src/libos/src/fs/hostfs.rs +++ b/src/libos/src/fs/hostfs.rs @@ -269,10 +269,9 @@ impl INode for HNode { return Err(FsError::NotDir); } let idx = ctx.pos(); - let mut total_written_len = 0; for entry in try_std!(self.path.read_dir()).skip(idx) { let entry = try_std!(entry); - let written_len = match ctx.write_entry( + if let Err(e) = ctx.write_entry( &entry .file_name() .into_string() @@ -283,18 +282,14 @@ impl INode for HNode { .map_err(|_| FsError::InvalidParam)? .into_fs_filetype(), ) { - Ok(written_len) => written_len, - Err(e) => { - if total_written_len == 0 { - return Err(e); - } else { - break; - } + if ctx.written_len() == 0 { + return Err(e); + } else { + break; } }; - total_written_len += written_len; } - Ok(total_written_len) + Ok(ctx.written_len()) } fn io_control(&self, cmd: u32, data: usize) -> Result<()> { diff --git a/src/libos/src/fs/procfs/mod.rs b/src/libos/src/fs/procfs/mod.rs index 5ae407db..640669f0 100644 --- a/src/libos/src/fs/procfs/mod.rs +++ b/src/libos/src/fs/procfs/mod.rs @@ -159,23 +159,22 @@ impl DirProcINode for LockedProcRootINode { fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result { let file = self.0.read().unwrap(); - let mut total_written_len = 0; let idx = ctx.pos(); // Write first two special entries if idx == 0 { let this_inode = file.this.upgrade().unwrap(); - write_inode_entry!(&mut ctx, ".", &this_inode, &mut total_written_len); + write_inode_entry!(&mut ctx, ".", &this_inode); } if idx <= 1 { let parent_inode = file.this.upgrade().unwrap(); - write_inode_entry!(&mut ctx, "..", &parent_inode, &mut total_written_len); + write_inode_entry!(&mut ctx, "..", &parent_inode); } // Write the non volatile entries let skipped = if idx < 2 { 0 } else { idx - 2 }; for (name, inode) in file.non_volatile_entries.iter().skip(skipped) { - write_inode_entry!(&mut ctx, name, inode, &mut total_written_len); + write_inode_entry!(&mut ctx, name, inode); } // Write the pid entries @@ -192,11 +191,10 @@ impl DirProcINode for LockedProcRootINode { &mut ctx, &process.pid().to_string(), PROC_INO, - vfs::FileType::Dir, - &mut total_written_len + vfs::FileType::Dir ); } - Ok(total_written_len) + Ok(ctx.written_len()) } } diff --git a/src/libos/src/fs/procfs/pid/fd.rs b/src/libos/src/fs/procfs/pid/fd.rs index 5e185288..65801a8e 100644 --- a/src/libos/src/fs/procfs/pid/fd.rs +++ b/src/libos/src/fs/procfs/pid/fd.rs @@ -55,32 +55,24 @@ impl DirProcINode for LockedProcFdDirINode { fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result { let file = self.0.read().unwrap(); - let mut total_written_len = 0; let idx = ctx.pos(); // Write first two special entries - write_first_two_entries!(idx, &mut ctx, &file, &mut total_written_len); + write_first_two_entries!(idx, &mut ctx, &file); // Write the fd entries let skipped = if idx < 2 { 0 } else { idx - 2 }; let main_thread = match file.process_ref.main_thread() { Some(main_thread) => main_thread, None => { - return Ok(total_written_len); + return Ok(ctx.written_len()); } }; let fds = main_thread.files().lock().unwrap().fds(); for fd in fds.iter().skip(skipped) { - write_entry!( - &mut ctx, - &fd.to_string(), - PROC_INO, - vfs::FileType::SymLink, - &mut total_written_len - ); + write_entry!(&mut ctx, &fd.to_string(), PROC_INO, vfs::FileType::SymLink); } - - Ok(total_written_len) + Ok(ctx.written_len()) } } diff --git a/src/libos/src/fs/procfs/pid/mod.rs b/src/libos/src/fs/procfs/pid/mod.rs index ab82d214..2ff75736 100644 --- a/src/libos/src/fs/procfs/pid/mod.rs +++ b/src/libos/src/fs/procfs/pid/mod.rs @@ -115,29 +115,21 @@ impl DirProcINode for LockedPidDirINode { fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> vfs::Result { let file = self.0.read().unwrap(); - let mut total_written_len = 0; let idx = ctx.pos(); // Write first two special entries - write_first_two_entries!(idx, &mut ctx, &file, &mut total_written_len); + write_first_two_entries!(idx, &mut ctx, &file); // Write the normal entries let skipped = if idx < 2 { 0 } else { idx - 2 }; for (name, inode) in file.entries.iter().skip(skipped) { - write_inode_entry!(&mut ctx, name, inode, &mut total_written_len); + write_inode_entry!(&mut ctx, name, inode); } // Write the fd entry if idx <= 2 + file.entries.len() { - write_entry!( - &mut ctx, - "fd", - PROC_INO, - vfs::FileType::Dir, - &mut total_written_len - ); + write_entry!(&mut ctx, "fd", PROC_INO, vfs::FileType::Dir); } - - Ok(total_written_len) + Ok(ctx.written_len()) } } diff --git a/src/libos/src/fs/procfs/proc_inode/mod.rs b/src/libos/src/fs/procfs/proc_inode/mod.rs index 131110b6..bd532b95 100644 --- a/src/libos/src/fs/procfs/proc_inode/mod.rs +++ b/src/libos/src/fs/procfs/proc_inode/mod.rs @@ -66,52 +66,45 @@ macro_rules! impl_inode_for_file_or_symlink { #[macro_export] macro_rules! write_first_two_entries { - ($idx: expr, $ctx:expr, $file:expr, $total_written:expr) => { + ($idx: expr, $ctx:expr, $file:expr) => { let idx = $idx; let file = $file; if idx == 0 { let this_inode = file.this.upgrade().unwrap(); - write_inode_entry!($ctx, ".", &this_inode, $total_written); + write_inode_entry!($ctx, ".", &this_inode); } if idx <= 1 { - write_inode_entry!($ctx, "..", &file.parent, $total_written); + write_inode_entry!($ctx, "..", &file.parent); } }; } #[macro_export] macro_rules! write_inode_entry { - ($ctx:expr, $name:expr, $inode:expr, $total_written:expr) => { + ($ctx:expr, $name:expr, $inode:expr) => { let ctx = $ctx; let name = $name; let ino = $inode.metadata()?.inode; let type_ = $inode.metadata()?.type_; - let total_written = $total_written; - write_entry!(ctx, name, ino, type_, total_written); + write_entry!(ctx, name, ino, type_); }; } #[macro_export] macro_rules! write_entry { - ($ctx:expr, $name:expr, $ino:expr, $type_:expr, $total_written:expr) => { + ($ctx:expr, $name:expr, $ino:expr, $type_:expr) => { let ctx = $ctx; let name = $name; let ino = $ino; let type_ = $type_; - let total_written = $total_written; - match ctx.write_entry(name, ino as u64, type_) { - Ok(written_len) => { - *total_written += written_len; - } - Err(e) => { - if *total_written == 0 { - return Err(e); - } else { - return Ok(*total_written); - } + if let Err(e) = ctx.write_entry(name, ino as u64, type_) { + if ctx.written_len() == 0 { + return Err(e); + } else { + return Ok(ctx.written_len()); } } };