feat(stdfscall): flocking

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2026-02-24 01:12:47 +11:00
committed by Jeremy Soller
parent 14349d1649
commit 955b4b2a1c
3 changed files with 70 additions and 12 deletions
+14 -1
View File
@@ -26,7 +26,8 @@ pub struct FileDescription {
bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct InternalFlags: u32 {
const POSITIONED = 1;
const POSITIONED = 1 << 0;
const NOTIFY_ON_NEXT_DETACH = 1 << 1;
}
}
impl FileDescription {
@@ -82,9 +83,21 @@ impl FileDescription {
impl FileDescriptor {
pub fn close(self, token: &mut CleanLockToken) -> Result<()> {
{
let description = self.description.read();
if description
.internal_flags
.contains(InternalFlags::NOTIFY_ON_NEXT_DETACH)
{
let scheme = scheme::get_scheme(token.token(), description.scheme)?;
scheme.detach(description.number, token)?;
}
}
if let Ok(file) = Arc::try_unwrap(self.description).map(RwLock::into_inner) {
file.try_close(token)?;
}
Ok(())
}
}
+4
View File
@@ -652,6 +652,9 @@ pub trait KernelScheme: Send + Sync + 'static {
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
Ok(())
}
fn detach(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
Ok(())
}
fn kcall(
&self,
id: usize,
@@ -665,6 +668,7 @@ pub trait KernelScheme: Send + Sync + 'static {
fn kstdfscall(
&self,
id: usize,
desc: Arc<SpinRwLock<FileDescription>>,
payload: UserSliceRw,
flags: CallFlags,
metadata: &[u64],
+52 -11
View File
@@ -68,7 +68,7 @@ enum State {
#[derive(Debug)]
enum Response {
Regular(Result<usize>, u8),
Regular(Result<usize>, u8, bool),
Fd(Arc<RwLock<FileDescription>>),
MultipleFds(Option<Vec<Arc<RwLock<FileDescription>>>>),
}
@@ -76,7 +76,7 @@ enum Response {
impl Response {
fn as_regular(self) -> Result<usize> {
match self {
Response::Regular(res, _) => res,
Response::Regular(res, _, _) => res,
Response::Fd(_) | Response::MultipleFds(_) => Err(Error::new(EIO)),
}
}
@@ -116,6 +116,11 @@ enum ParsedCqe {
base_addr: VirtualAddress,
page_count: usize,
},
RespondAndNotifyOnDetach {
tag: u32,
res: Result<usize>,
extra0: u8,
},
}
impl ParsedCqe {
fn parse_cqe(cqe: &Cqe) -> Result<Self> {
@@ -126,6 +131,11 @@ impl ParsedCqe {
res: Error::demux(cqe.result as usize),
extra0: cqe.extra_raw[0],
},
CqeOpcode::RespondAndNotifyOnDetach => Self::RespondAndNotifyOnDetach {
tag: cqe.tag,
res: Error::demux(cqe.result as usize),
extra0: cqe.extra_raw[0],
},
CqeOpcode::RespondWithFd => Self::ResponseWithFd {
tag: cqe.tag,
fd: cqe.result as usize,
@@ -765,7 +775,10 @@ impl UserInner {
fn handle_parsed(&self, cqe: &ParsedCqe, token: &mut CleanLockToken) -> Result<()> {
match *cqe {
ParsedCqe::RegularResponse { tag, res, extra0 } => {
self.respond(tag, Response::Regular(res, extra0), token)?
self.respond(tag, Response::Regular(res, extra0, false), token)?
}
ParsedCqe::RespondAndNotifyOnDetach { tag, res, extra0 } => {
self.respond(tag, Response::Regular(res, extra0, true), token)?
}
ParsedCqe::ResponseWithFd { tag, fd } => self.respond(
tag,
@@ -917,7 +930,7 @@ impl UserInner {
} => {
// Convert ECANCELED to EINTR if a request was being canceled (currently always
// due to signals).
if let Response::Regular(ref mut res, _) = response
if let Response::Regular(ref mut res, _, _) = response
&& canceling
&& *res == Err(Error::new(ECANCELED))
{
@@ -925,7 +938,7 @@ impl UserInner {
}
// TODO: Require ECANCELED?
if let Response::Regular(ref mut res, _) = response
if let Response::Regular(ref mut res, _, _) = response
&& !canceling
&& *res == Err(Error::new(EINTR))
{
@@ -1362,7 +1375,7 @@ impl KernelScheme for UserScheme {
address.release()?;
match result? {
Response::Regular(res, fl) => Ok({
Response::Regular(res, fl, _) => Ok({
let fd = res?;
OpenResult::SchemeLocal(
fd,
@@ -1583,6 +1596,25 @@ impl KernelScheme for UserScheme {
Ok(())
}
fn detach(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
println!("detach(id={id}");
let ctx = { context::current().read(token.token()).caller_ctx() };
self.inner.todo.send(
Sqe {
opcode: Opcode::Detach as u8,
sqe_flags: SqeFlags::empty(),
_rsvd: 0,
tag: 0,
args: [id as u64, 0, 0, 0, 0, 0],
caller: ctx.pid as u64,
},
token,
);
event::trigger(self.inner.root_id, self.inner.scheme_id.get(), EVENT_READ);
Ok(())
}
fn kdup(
&self,
file: usize,
@@ -1604,7 +1636,7 @@ impl KernelScheme for UserScheme {
address.release()?;
match result? {
Response::Regular(res, fl) => Ok({
Response::Regular(res, fl, _) => Ok({
let fd = res?;
OpenResult::SchemeLocal(
fd,
@@ -1864,6 +1896,7 @@ impl KernelScheme for UserScheme {
fn kstdfscall(
&self,
id: usize,
desc: Arc<spin::RwLock<FileDescription>>,
payload: UserSliceRw,
_flags: CallFlags,
metadata: &[u64],
@@ -1894,10 +1927,18 @@ impl KernelScheme for UserScheme {
let len = dst.len().min(metadata.len());
dst[..len].copy_from_slice(&metadata[..len]);
}
inner
.call_inner(Vec::new(), sqe, address.span(), token)?
.as_regular()
match inner.call_inner(Vec::new(), sqe, address.span(), token)? {
Response::Regular(res, _, notify_on_detach) => {
desc.write()
.internal_flags
.set(InternalFlags::NOTIFY_ON_NEXT_DETACH, notify_on_detach);
res
}
_ => Err(Error::new(EIO)),
}
}
fn kfdwrite(
&self,
number: usize,
@@ -1960,7 +2001,7 @@ impl KernelScheme for UserScheme {
)?;
let descriptions_opt = match res {
Response::Regular(res, _) => {
Response::Regular(res, _, _) => {
return match res {
Ok(_) => Err(Error::new(EIO)),
Err(e) => Err(e),