WIP: Add getdents opaque_id
This commit is contained in:
@@ -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)]
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user