WIP: Add getdents opaque_id

This commit is contained in:
4lDO2
2024-09-10 09:10:41 +02:00
parent 339271b4d7
commit 97f60de4ef
10 changed files with 126 additions and 29 deletions
+1
View File
@@ -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)]
-1
View File
@@ -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();
+24 -4
View File
@@ -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<usize> {
fn getdents(
&self,
id: usize,
buf: UserSliceWo,
header_size: u16,
opaque: u64,
) -> Result<usize> {
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<()> {
+38 -11
View File
@@ -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<usize> {
fn getdents(
&self,
id: usize,
buf: UserSliceWo,
header_size: u16,
opaque_id_start: u64,
) -> Result<usize> {
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)),
+7 -1
View File
@@ -451,7 +451,13 @@ pub trait KernelScheme: Send + Sync + 'static {
) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
fn getdents(&self, id: usize, buf: UserSliceWo, header_size: u16) -> Result<usize> {
fn getdents(
&self,
id: usize,
buf: UserSliceWo,
header_size: u16,
opaque_id_first: u64,
) -> Result<usize> {
Err(Error::new(EOPNOTSUPP))
}
+18 -4
View File
@@ -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<usize> {
fn getdents(
&self,
id: usize,
buf: UserSliceWo,
header_size: u16,
opaque: u64,
) -> Result<usize> {
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,
})?;
}
}
+18 -4
View File
@@ -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<usize> {
fn getdents(
&self,
id: usize,
buf: UserSliceWo,
header_size: u16,
first_index: u64,
) -> Result<usize> {
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())
}
+18 -2
View File
@@ -1554,12 +1554,28 @@ impl KernelScheme for UserScheme {
address.release()?;
result
}
fn getdents(&self, file: usize, stat: UserSliceWo, header_size: u16) -> Result<usize> {
fn getdents(
&self,
file: usize,
stat: UserSliceWo,
header_size: u16,
opaque_id_start: u64,
) -> Result<usize> {
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()?;
+1 -1
View File
@@ -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| {
+1 -1
Submodule syscall updated: c043410366...4d159ce1c7