From 97f60de4efb54eb28c81ea0925a2e3ca0f7ecaae Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 10 Sep 2024 09:10:41 +0200 Subject: [PATCH] WIP: Add getdents opaque_id --- src/main.rs | 1 + src/panic.rs | 1 - src/scheme/acpi.rs | 28 +++++++++++++++++++++---- src/scheme/irq.rs | 49 +++++++++++++++++++++++++++++++++---------- src/scheme/mod.rs | 8 ++++++- src/scheme/root.rs | 22 +++++++++++++++---- src/scheme/sys/mod.rs | 22 +++++++++++++++---- src/scheme/user.rs | 20 ++++++++++++++++-- src/syscall/mod.rs | 2 +- syscall | 2 +- 10 files changed, 126 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index a2c18145bf..bb1223aba0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,7 @@ // Ensure that all must_use results are used #![deny(unused_must_use)] #![feature(allocator_api)] +#![feature(asm_const)] #![feature(int_roundings)] #![feature(iter_next_chunk)] #![feature(let_chains)] diff --git a/src/panic.rs b/src/panic.rs index 50ba36a27e..92cb9879f2 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -8,7 +8,6 @@ use crate::{context, cpu_id, interrupt, syscall}; #[panic_handler] fn rust_begin_unwind(info: &PanicInfo) -> ! { println!("KERNEL PANIC: {}", info); - loop {} unsafe { interrupt::stack_trace(); diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index 4ae38b659b..fc02077695 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -8,7 +8,7 @@ use alloc::{boxed::Box, collections::BTreeMap}; use spin::{Mutex, Once, RwLock}; use syscall::{ - dirent::{DirentBuf, DirentKind}, + dirent::{DirEntry, DirentBuf, DirentKind}, EIO, }; @@ -239,7 +239,13 @@ impl KernelScheme for AcpiScheme { dst_buf.copy_common_bytes_from_slice(src_buf) } - fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + id: usize, + buf: UserSliceWo, + header_size: u16, + opaque: u64, + ) -> Result { let Some(Handle { kind: HandleKind::TopLevel, .. @@ -249,8 +255,22 @@ impl KernelScheme for AcpiScheme { }; let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?; - buf.entry(DirentKind::Regular, "rxsdt")?; - buf.entry(DirentKind::Socket, "kstop")?; + if opaque == 0 { + buf.entry(DirEntry { + kind: DirentKind::Regular, + name: "rxsdt", + inode: 0, + next_opaque_id: 1, + })?; + } + if opaque <= 1 { + buf.entry(DirEntry { + kind: DirentKind::Socket, + name: "kstop", + inode: 0, + next_opaque_id: u64::MAX, + })?; + } Ok(buf.finalize()) } fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> { diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 238996c9aa..1c87bae7e3 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -10,7 +10,7 @@ use core::{ use alloc::{collections::BTreeMap, string::String, vec::Vec}; use spin::{Mutex, Once, RwLock}; -use syscall::dirent::{DirentBuf, DirentKind}; +use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; use crate::{ arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_reserved}, @@ -216,7 +216,17 @@ impl crate::scheme::KernelScheme for IrqScheme { HANDLES.write().insert(fd, handle); Ok(OpenResult::SchemeLocal(fd, int_flags)) } - fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + id: usize, + buf: UserSliceWo, + header_size: u16, + opaque_id_start: u64, + ) -> Result { + let Ok(opaque) = usize::try_from(opaque_id_start) else { + return Ok(0); + }; + use core::fmt::Write; let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?; @@ -224,26 +234,43 @@ impl crate::scheme::KernelScheme for IrqScheme { match *HANDLES.read().get(&id).ok_or(Error::new(EBADF))? { Handle::TopLevel => { - // list every logical CPU in the format of e.g. `cpu-1b` - for cpu_id in CPUS.get().expect("IRQ scheme not initialized") { - intermediate.clear(); - write!(&mut intermediate, "cpu-{:02x}", cpu_id).unwrap(); - buf.entry(DirentKind::Directory, &intermediate)?; + let cpus = CPUS.get().expect("IRQ scheme not initialized"); + + if bsp_apic_id().is_some() && opaque == 0 { + buf.entry(DirEntry { + inode: 0, + next_opaque_id: 1, + kind: DirentKind::CharDev, + name: "bsp", + })?; } - if bsp_apic_id().is_some() { - buf.entry(DirentKind::CharDev, "bsp")?; + // list every logical CPU in the format of e.g. `cpu-1b` + for cpu_id in cpus.iter().filter(|i| opaque <= usize::from(**i)) { + intermediate.clear(); + write!(&mut intermediate, "cpu-{:02x}", cpu_id).unwrap(); + buf.entry(DirEntry { + kind: DirentKind::Directory, + name: &intermediate, + inode: 0, + next_opaque_id: u64::from(*cpu_id + 1), + })?; } } Handle::Avail(cpu_id) => { - for vector in available_irqs_iter(LogicalCpuId::new(cpu_id.into())) { + for vector in available_irqs_iter(LogicalCpuId::new(cpu_id.into())).skip(opaque) { let irq = vector_to_irq(vector); if Some(u32::from(cpu_id)) == bsp_apic_id() && irq < BASE_IRQ_COUNT { continue; } intermediate.clear(); write!(intermediate, "{}", irq).unwrap(); - buf.entry(DirentKind::CharDev, &intermediate)?; + buf.entry(DirEntry { + inode: 0, + kind: DirentKind::CharDev, + name: &intermediate, + next_opaque_id: u64::from(vector) + 1, + })?; } } _ => return Err(Error::new(ENOTDIR)), diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 499cc65e47..ac92474acc 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -451,7 +451,13 @@ pub trait KernelScheme: Send + Sync + 'static { ) -> Result { Err(Error::new(EOPNOTSUPP)) } - fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + id: usize, + buf: UserSliceWo, + header_size: u16, + opaque_id_first: u64, + ) -> Result { Err(Error::new(EOPNOTSUPP)) } diff --git a/src/scheme/root.rs b/src/scheme/root.rs index c7f3b699b7..8632cd76b2 100644 --- a/src/scheme/root.rs +++ b/src/scheme/root.rs @@ -6,7 +6,7 @@ use core::{ use hashbrown::HashMap; use spin::RwLock; use syscall::{ - dirent::{DirentBuf, DirentKind}, + dirent::{DirEntry, DirentBuf, DirentKind}, O_FSYNC, }; @@ -240,7 +240,13 @@ impl KernelScheme for RootScheme { Handle::List { .. } => Err(Error::new(EISDIR)), } } - fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + id: usize, + buf: UserSliceWo, + header_size: u16, + opaque: u64, + ) -> Result { let Handle::List { ens } = *self.handles.read().get(&id).ok_or(Error::new(EBADF))? else { return Err(Error::new(ENOTDIR)); }; @@ -248,8 +254,16 @@ impl KernelScheme for RootScheme { let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?; { let schemes = scheme::schemes(); - for (name, _scheme_id) in schemes.iter_name(ens) { - buf.entry(DirentKind::Unspecified, name)?; + for (name, scheme_id) in schemes + .iter_name(ens) + .filter(|(_, s)| opaque <= s.get() as u64) + { + buf.entry(DirEntry { + kind: DirentKind::Unspecified, + name, + inode: 0, + next_opaque_id: scheme_id.get() as u64 + 1, + })?; } } diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index 4a8b90a4d4..ce5b55ea9c 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -1,5 +1,5 @@ use ::syscall::{ - dirent::{DirentBuf, DirentKind}, + dirent::{DirEntry, DirentBuf, DirentKind}, EIO, EISDIR, ENOTDIR, }; use alloc::{collections::BTreeMap, vec::Vec}; @@ -150,13 +150,27 @@ impl KernelScheme for SysScheme { } } } - fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + id: usize, + buf: UserSliceWo, + header_size: u16, + first_index: u64, + ) -> Result { + let Ok(first_index) = usize::try_from(first_index) else { + return Ok(0); + }; match HANDLES.read().get(&id).ok_or(Error::new(EBADF))? { Handle::Resource { .. } => return Err(Error::new(ENOTDIR)), Handle::TopLevel => { let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?; - for (name, _) in FILES { - buf.entry(DirentKind::Regular, name)?; + for (this_idx, (name, _)) in FILES.iter().enumerate().skip(first_index) { + buf.entry(DirEntry { + inode: this_idx as u64, + next_opaque_id: this_idx as u64 + 1, + kind: DirentKind::Regular, + name, + })?; } Ok(buf.finalize()) } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index f3fffe81d9..53e6542706 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -1554,12 +1554,28 @@ impl KernelScheme for UserScheme { address.release()?; result } - fn getdents(&self, file: usize, stat: UserSliceWo, header_size: u16) -> Result { + fn getdents( + &self, + file: usize, + stat: UserSliceWo, + header_size: u16, + opaque_id_start: u64, + ) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.capture_user(stat)?; + // TODO: Support passing the 16-byte record_len of the last dent, to make it possible to + // iterate backwards without first interating forward? The last entry will contain the + // opaque id to pass to the next getdents. Since this field is small, this would fit in the + // extra_raw field of `Cqe`s. let result = inner.call( Opcode::Getdents, - [file, address.base(), address.len(), header_size.into()], + [ + file, + address.base(), + address.len(), + header_size.into(), + opaque_id_start as usize, + ], address.span(), ); address.release()?; diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index e933e1a5e0..4d77d14904 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -114,7 +114,7 @@ pub fn syscall( } file_op_generic(fd, |scheme, number| { - scheme.getdents(number, UserSlice::wo(c, d)?, header_size) + scheme.getdents(number, UserSlice::wo(c, d)?, header_size, f as u64) }) } SYS_FUTIMENS => file_op_generic(fd, |scheme, number| { diff --git a/syscall b/syscall index c043410366..4d159ce1c7 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit c043410366e61345902808df8337e16623465035 +Subproject commit 4d159ce1c77e2caaefe3ff7667d720a498e7c8e6