diff --git a/tokio/src/fs/remove_dir.rs b/tokio/src/fs/remove_dir.rs index 5407af0dde1..20bda1c56e2 100644 --- a/tokio/src/fs/remove_dir.rs +++ b/tokio/src/fs/remove_dir.rs @@ -7,6 +7,33 @@ use std::path::Path; /// /// This is an async version of [`std::fs::remove_dir`]. pub async fn remove_dir(path: impl AsRef) -> io::Result<()> { - let path = path.as_ref().to_owned(); + let path = path.as_ref(); + + #[cfg(all( + tokio_unstable, + feature = "io-uring", + feature = "rt", + feature = "fs", + target_os = "linux", + ))] + { + use crate::io::uring::unlink::Unlink; + use crate::runtime::driver::op::Op; + + let handle = crate::runtime::Handle::current(); + let driver_handle = handle.inner.driver().io(); + + type OpUnlink = Op; + + if driver_handle.check_and_init(OpUnlink::CODE)? { + return OpUnlink::remove_dir(path)?.await; + } + } + + remove_dir_blocking(path).await +} + +async fn remove_dir_blocking(path: &Path) -> io::Result<()> { + let path = path.to_owned(); asyncify(move || std::fs::remove_dir(path)).await } diff --git a/tokio/src/fs/remove_file.rs b/tokio/src/fs/remove_file.rs index 4018802547e..146741db36b 100644 --- a/tokio/src/fs/remove_file.rs +++ b/tokio/src/fs/remove_file.rs @@ -11,6 +11,32 @@ use std::path::Path; /// /// This is an async version of [`std::fs::remove_file`]. pub async fn remove_file(path: impl AsRef) -> io::Result<()> { - let path = path.as_ref().to_owned(); + let path = path.as_ref(); + + #[cfg(all( + tokio_unstable, + feature = "io-uring", + feature = "rt", + feature = "fs", + target_os = "linux", + ))] + { + use crate::io::uring::unlink::Unlink; + use crate::runtime::driver::op::Op; + + let handle = crate::runtime::Handle::current(); + let driver_handle = handle.inner.driver().io(); + type OpUnlink = Op; + + if driver_handle.check_and_init(OpUnlink::CODE)? { + return OpUnlink::remove_file(path)?.await; + } + } + + remove_file_blocking(path).await +} + +async fn remove_file_blocking(path: &Path) -> io::Result<()> { + let path = path.to_owned(); asyncify(move || std::fs::remove_file(path)).await } diff --git a/tokio/src/io/uring/mod.rs b/tokio/src/io/uring/mod.rs index facad596f63..ae95dc8cab2 100644 --- a/tokio/src/io/uring/mod.rs +++ b/tokio/src/io/uring/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod open; pub(crate) mod read; +pub(crate) mod unlink; pub(crate) mod utils; pub(crate) mod write; diff --git a/tokio/src/io/uring/unlink.rs b/tokio/src/io/uring/unlink.rs new file mode 100644 index 00000000000..04d152721b0 --- /dev/null +++ b/tokio/src/io/uring/unlink.rs @@ -0,0 +1,59 @@ +use crate::io::uring::utils::cstr; +use crate::runtime::driver::op::{CancelData, Cancellable, Completable, CqeResult, Op}; +use io_uring::{opcode, types}; +use std::ffi::CString; +use std::io; +use std::io::Error; +use std::path::Path; + +#[derive(Debug)] +pub(crate) struct Unlink { + /// This field will be read by the kernel during the operation, so we + /// need to ensure it is valid for the entire duration of the operation. + #[allow(dead_code)] + path: CString, +} + +impl Completable for Unlink { + type Output = io::Result<()>; + + fn complete(self, cqe: CqeResult) -> Self::Output { + cqe.result.map(drop) + } + + fn complete_with_error(self, error: Error) -> Self::Output { + Err(error) + } +} + +impl Cancellable for Unlink { + fn cancel(self) -> CancelData { + CancelData::Unlink(self) + } +} + +impl Op { + pub(crate) const CODE: u8 = opcode::UnlinkAt::CODE; + + /// Submit a request to unlink a file or directory. + fn unlink(path: &Path, directory: bool) -> io::Result> { + let path = cstr(path)?; + + let flags = if directory { libc::AT_REMOVEDIR } else { 0 }; + + let unlink_op = opcode::UnlinkAt::new(types::Fd(libc::AT_FDCWD), path.as_ptr()) + .flags(flags) + .build(); + + // SAFETY: Parameters are valid for the entire duration of the operation + Ok(unsafe { Op::new(unlink_op, Unlink { path }) }) + } + + pub(crate) fn remove_file(path: &Path) -> io::Result> { + Self::unlink(path, false) + } + + pub(crate) fn remove_dir(path: &Path) -> io::Result> { + Self::unlink(path, true) + } +} diff --git a/tokio/src/runtime/driver/op.rs b/tokio/src/runtime/driver/op.rs index d2b9289ceee..415af238c58 100644 --- a/tokio/src/runtime/driver/op.rs +++ b/tokio/src/runtime/driver/op.rs @@ -1,8 +1,9 @@ -use crate::io::uring::open::Open; use crate::io::uring::read::Read; use crate::io::uring::write::Write; use crate::runtime::Handle; +use crate::io::uring::open::Open; +use crate::io::uring::unlink::Unlink; use io_uring::cqueue; use io_uring::squeue::Entry; use std::future::Future; @@ -19,6 +20,7 @@ pub(crate) enum CancelData { Open(Open), Write(Write), Read(Read), + Unlink(Unlink), } #[derive(Debug)]