Skip to content

Commit

Permalink
WIP: statx
Browse files Browse the repository at this point in the history
  • Loading branch information
problame committed Feb 5, 2024
1 parent abd0604 commit 12d698f
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 1 deletion.
1 change: 1 addition & 0 deletions tokio-epoll-uring/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod fsync;
pub mod nop;
pub mod open_at;
pub mod read;
pub mod statx;
131 changes: 131 additions & 0 deletions tokio-epoll-uring/src/ops/statx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use std::os::fd::AsRawFd;
use uring_common::libc;

use uring_common::{
io_fd::IoFd,
io_uring::{self},
};

use crate::system::submission::op_fut::Op;

// See `https://man.archlinux.org/man/statx.2.en#Invoking_%3Cb%3Estatx%3C/b%3E():`
// to understand why there are different variants and why they're named the way they are.
pub enum StatxOp<F>
where
F: IoFd + Send,
{
ByFileDescriptor {
file: F,
statxbuf: Submitting<
Box<uring_common::io_uring::types::statx>,
*mut uring_common::io_uring::types::statx,
>,
},
}

impl<F> StatxOp<F>
where
F: IoFd + Send,
{
// Do the equivalent of fstat.
pub fn new_fstat(file: F, statxbuf: Box<uring_common::io_uring::types::statx>) -> StatxOp<F> {
StatxOp::ByFileDescriptor {
file,
statxbuf: Submitting::No(statxbuf),
}
}
}

pub enum Resources<F>
where
F: IoFd + Send,
{
ByFileDescriptor {
file: F,
statxbuf: Box<uring_common::io_uring::types::statx>,
},
}

// TODO: refine the `Op` trait so we encode this state in the typesystem
enum Submitting<A, B> {
No(A),
Yes(B),
}

/// SAFETY: we only needs this because we store the pointer while Submitting::Yes
unsafe impl<F> Send for StatxOp<F> where F: IoFd + Send {}

impl<F> crate::sealed::Sealed for StatxOp<F> where F: IoFd + Send {}

impl<F> Op for StatxOp<F>
where
F: IoFd + Send,
{
type Resources = Resources<F>;
type Success = ();
type Error = std::io::Error;

fn make_sqe(&mut self) -> io_uring::squeue::Entry {
// See https://man.archlinux.org/man/statx.2.en#Invoking_%3Cb%3Estatx%3C/b%3E():
match self {
StatxOp::ByFileDescriptor { file, statxbuf } => {
let fd = io_uring::types::Fd(
// SAFETY: we hold `F` in self, and if `self` is dropped, we hand the fd to the
// `System` to keep it live until the operation completes.
#[allow(unused_unsafe)]
unsafe {
file.as_fd().as_raw_fd()
},
);
// SAFETY: by Box::into_raw'ing the statxbuf box, the memory won't be re-used
// until we Box::from_raw it in `on_failed_submission` or `on_op_completion`
let statxbuf: *mut uring_common::io_uring::types::statx = match statxbuf {
Submitting::No(statxbuf_box) => Box::into_raw(statxbuf_box),
Submitting::Yes(statxbuf_ptr) => {
unreachable!("make_sqe is only called once")
}
};
// This is equivalent to what rust std 1.75 does if statx is supported
io_uring::opcode::Statx::new(fd, b"\0" as *const _, statxbuf)
.flags(libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT)
.mask(uring_common::libc::STATX_ALL)
.build()
}
}
}

fn on_failed_submission(self) -> Self::Resources {
self.on_ownership_back_with_userspace()
}

fn on_op_completion(self, res: i32) -> (Self::Resources, Result<Self::Success, Self::Error>) {
// https://man.archlinux.org/man/io_uring_prep_statx.3.en
let res = if res < 0 {
Err(std::io::Error::from_raw_os_error(-res))
} else {
Ok(())
};
(self.on_ownership_back_with_userspace(), res)
}
}

impl<F> StatxOp<F>
where
F: IoFd + Send,
{
fn on_ownership_back_with_userspace(self) -> Resources<F> {
match self {
StatxOp::ByFileDescriptor { file, statxbuf } => {
let statxbuf = match statxbuf {
Submitting::No(_) => unreachable!("only called after make_sqe"),
Submitting::Yes(statxbuf_ptr) => {
// SAFETY: the `System` guarantees that when it calls us here,
// ownership of the resources is with us.
unsafe { Box::from_raw(statxbuf_ptr) }
}
};
Resources::ByFileDescriptor { file, statxbuf }
}
}
}
}
13 changes: 12 additions & 1 deletion tokio-epoll-uring/src/system/lifecycle/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{os::fd::OwnedFd, path::Path, task::ready};
use uring_common::{buf::BoundedBufMut, io_fd::IoFd};

use crate::{
ops::{fsync::FsyncOp, open_at::OpenAtOp, read::ReadOp},
ops::{fsync::FsyncOp, open_at::OpenAtOp, read::ReadOp, statx::StatxOp},
system::submission::{op_fut::execute_op, SubmitSide},
};

Expand Down Expand Up @@ -171,4 +171,15 @@ impl crate::SystemHandle {
let inner = self.inner.as_ref().unwrap();
execute_op(op, inner.submit_side.weak(), None).await
}

pub async fn statx<F: IoFd + Send>(
&self,
file: F,
) -> (
F, Result<uring_common::io_uring::types::statx, crate::system::submission::op_fut::Error<std::io::Error>>
) {
uring_common::io_uring::types::statx
let op = StatxOp::new_fstat(file, statxbuf)

}
}
2 changes: 2 additions & 0 deletions uring-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ pub mod io_fd;

#[cfg(target_os = "linux")]
pub use io_uring;
#[cfg(target_os = "linux")]
pub use libc;

0 comments on commit 12d698f

Please sign in to comment.