Skip to content

Commit

Permalink
implement open_at
Browse files Browse the repository at this point in the history
* Vendor in `OpenOptions` from `tokio-uring.git:d5e90539bd6d1c518e848298564a098c300866bc`
* Remove the `OpenOptions::open()` function which is
  `tokio-uring`-specific
* Add the extension trait that allows for conversion of OpenOptions into
  an `io_uring::squeue::Entry`
* Use it throughout the code base.
  • Loading branch information
problame committed Nov 20, 2023
1 parent 16d09a9 commit e4b5d6c
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 2 deletions.
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 @@ -4,4 +4,5 @@
pub use crate::system::submission::op_fut::Op;

pub mod nop;
pub mod open_at;
pub mod read;
59 changes: 59 additions & 0 deletions tokio-epoll-uring/src/ops/open_at.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::system::submission::op_fut::Op;
use std::ffi::CString;
use std::os::fd::{FromRawFd, OwnedFd};
use std::os::unix::prelude::OsStrExt;
use std::path::Path;

use uring_common::io_uring;
pub use uring_common::open_options::OpenOptions;

pub struct OpenAtOp {
dir_fd: Option<OwnedFd>,
_path: CString, // need to keep it alive for lifetime of the operation
sqe: io_uring::squeue::Entry,
}

impl OpenAtOp {
pub(crate) fn new_cwd(path: &Path, options: &OpenOptions) -> std::io::Result<Self> {
let path = CString::new(path.as_os_str().as_bytes())?;
// SAFETY: we keep `pathname` alive inside the OpenAtOp, so, the pointer stored int the SQE remains valid.
let sqe = unsafe {
uring_common::open_options_io_uring_ext::OpenOptionsIoUringExt::as_openat_sqe(
options,
path.as_c_str().as_ptr(),
)
}?;
Ok(OpenAtOp {
dir_fd: None,
_path: path,
sqe,
})
}
}

impl crate::sealed::Sealed for OpenAtOp {}

impl Op for OpenAtOp {
type Resources = Option<OwnedFd>;
type Success = OwnedFd;
type Error = std::io::Error;

fn make_sqe(&mut self) -> io_uring::squeue::Entry {
self.sqe.clone()
}

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

fn on_op_completion(self, res: i32) -> (Self::Resources, Result<Self::Success, Self::Error>) {
// https://man.archlinux.org/man/io_uring_prep_openat.3.en
// and https://man.archlinux.org/man/openat.2.en
let res = if res < 0 {
Err(std::io::Error::from_raw_os_error(-res))
} else {
Ok(unsafe { OwnedFd::from_raw_fd(res) })
};
(self.dir_fd, res)
}
}
26 changes: 24 additions & 2 deletions tokio-epoll-uring/src/system/lifecycle/handle.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Owned handle to an explicitly [`System::launch`](crate::System::launch)ed system.
use futures::FutureExt;
use std::{os::fd::OwnedFd, task::ready};
use std::{os::fd::OwnedFd, path::Path, task::ready};
use uring_common::buf::IoBufMut;

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

Expand Down Expand Up @@ -119,4 +119,26 @@ impl crate::SystemHandle {
let inner = self.inner.as_ref().unwrap();
execute_op(op, inner.submit_side.weak(), None)
}
pub fn open<P: AsRef<Path>>(
&self,
path: P,
options: &crate::ops::open_at::OpenOptions,
) -> impl std::future::Future<
Output = Result<OwnedFd, crate::system::submission::op_fut::Error<std::io::Error>>,
> {
let op = match OpenAtOp::new_cwd(path.as_ref(), options) {
Ok(op) => op,
Err(e) => {
return futures::future::Either::Left(async move {
Err(crate::system::submission::op_fut::Error::Op(e))
})
}
};
let inner = self.inner.as_ref().unwrap();
let weak = inner.submit_side.weak();
futures::future::Either::Right(async move {
let (_, res) = execute_op(op, weak, None).await;
res
})
}
}
2 changes: 2 additions & 0 deletions uring-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod buf;
pub mod open_options;
pub mod open_options_io_uring_ext;

pub use io_uring;
Loading

0 comments on commit e4b5d6c

Please sign in to comment.