From 6c06efb83942e5e3550f9a02c6511993b7ee824c Mon Sep 17 00:00:00 2001 From: Yuyi Wang Date: Thu, 29 Jan 2026 22:21:03 +0800 Subject: [PATCH 1/2] fix(driver): full iour fallback --- compio-driver/src/driver_type.rs | 6 +- compio-driver/src/sys/iour/mod.rs | 28 ++++--- compio-driver/src/sys/iour/op.rs | 117 +++++++++++++++++++++++++----- compio-driver/src/sys/poll/op.rs | 59 +++++---------- compio-driver/src/sys/unix_op.rs | 61 +++++++++++++++- 5 files changed, 194 insertions(+), 77 deletions(-) diff --git a/compio-driver/src/driver_type.rs b/compio-driver/src/driver_type.rs index fe9f3abf..b2942c9e 100644 --- a/compio-driver/src/driver_type.rs +++ b/compio-driver/src/driver_type.rs @@ -29,11 +29,7 @@ impl DriverType { Send::CODE, RecvMsg::CODE, SendMsg::CODE, - AsyncCancel::CODE, - OpenAt::CODE, - Close::CODE, - Splice::CODE, - Shutdown::CODE, + PollAdd::CODE, ]; if USED_OP.iter().all(|op| crate::sys::is_op_supported(*op)) { diff --git a/compio-driver/src/sys/iour/mod.rs b/compio-driver/src/sys/iour/mod.rs index 623c1fcc..d4edcb91 100644 --- a/compio-driver/src/sys/iour/mod.rs +++ b/compio-driver/src/sys/iour/mod.rs @@ -342,22 +342,30 @@ impl Driver { trace!(?personality, "push RawOp"); match entry { OpEntry::Submission(entry) => { - #[allow(clippy::useless_conversion)] - self.push_raw_with_key(entry.into(), key)?; - Poll::Pending + if is_op_supported(entry.get_opcode() as _) { + #[allow(clippy::useless_conversion)] + self.push_raw_with_key(entry.into(), key)?; + Poll::Pending + } else { + self.push_blocking_loop(key) + } } #[cfg(feature = "io-uring-sqe128")] OpEntry::Submission128(entry) => { self.push_raw_with_key(entry, key)?; Poll::Pending } - OpEntry::Blocking => loop { - if self.push_blocking(key.clone()) { - break Poll::Pending; - } else { - self.poll_blocking(); - } - }, + OpEntry::Blocking => self.push_blocking_loop(key), + } + } + + fn push_blocking_loop(&mut self, key: ErasedKey) -> Poll> { + loop { + if self.push_blocking(key.clone()) { + break Poll::Pending; + } else { + self.poll_blocking(); + } } } diff --git a/compio-driver/src/sys/iour/op.rs b/compio-driver/src/sys/iour/op.rs index f821f974..c077ecd5 100644 --- a/compio-driver/src/sys/iour/op.rs +++ b/compio-driver/src/sys/iour/op.rs @@ -69,6 +69,10 @@ unsafe impl OpCode for OpenFile { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for CloseFile { @@ -77,21 +81,21 @@ unsafe impl OpCode for CloseFile { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for TruncateFile { fn create_entry(self: Pin<&mut Self>) -> OpEntry { - if super::is_op_supported(opcode::Ftruncate::CODE) { - return opcode::Ftruncate::new(Fd(self.fd.as_fd().as_raw_fd()), self.size) - .build() - .into(); - } - - OpEntry::Blocking + opcode::Ftruncate::new(Fd(self.fd.as_fd().as_raw_fd()), self.size) + .build() + .into() } fn call_blocking(self: Pin<&mut Self>) -> io::Result { - self.truncate() + self.call() } } @@ -127,6 +131,19 @@ unsafe impl OpCode for FileStat { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + let this = self.project(); + static EMPTY_NAME: &[u8] = b"\0"; + let res = syscall!(libc::statx( + this.fd.as_fd().as_raw_fd(), + EMPTY_NAME.as_ptr().cast(), + libc::AT_EMPTY_PATH, + statx_mask(), + this.stat as *mut _ as _ + ))?; + Ok(res as _) + } } impl IntoInner for FileStat { @@ -171,6 +188,21 @@ unsafe impl OpCode for PathStat { .build() .into() } + + fn call_blocking(mut self: Pin<&mut Self>) -> io::Result { + let mut flags = libc::AT_EMPTY_PATH; + if !self.follow_symlink { + flags |= libc::AT_SYMLINK_NOFOLLOW; + } + let res = syscall!(libc::statx( + libc::AT_FDCWD, + self.path.as_ptr(), + flags, + statx_mask(), + std::ptr::addr_of_mut!(self.stat).cast() + ))?; + Ok(res as _) + } } impl IntoInner for PathStat { @@ -316,6 +348,10 @@ unsafe impl OpCode for Unlink { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for CreateDir { @@ -325,6 +361,10 @@ unsafe impl OpCode for CreateDir { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for Rename { @@ -338,6 +378,10 @@ unsafe impl OpCode for Rename { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for Symlink { @@ -350,6 +394,10 @@ unsafe impl OpCode for Symlink { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for HardLink { @@ -363,21 +411,21 @@ unsafe impl OpCode for HardLink { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for CreateSocket { fn create_entry(self: Pin<&mut Self>) -> OpEntry { - if super::is_op_supported(opcode::Socket::CODE) { - opcode::Socket::new( - self.domain, - self.socket_type | libc::SOCK_CLOEXEC, - self.protocol, - ) - .build() - .into() - } else { - OpEntry::Blocking - } + opcode::Socket::new( + self.domain, + self.socket_type | libc::SOCK_CLOEXEC, + self.protocol, + ) + .build() + .into() } fn call_blocking(self: Pin<&mut Self>) -> io::Result { @@ -395,6 +443,10 @@ unsafe impl OpCode for ShutdownSocket { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for CloseSocket { @@ -403,6 +455,10 @@ unsafe impl OpCode for CloseSocket { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + self.call() + } } unsafe impl OpCode for Accept { @@ -756,6 +812,29 @@ unsafe impl OpCode for Splice { .build() .into() } + + fn call_blocking(self: Pin<&mut Self>) -> io::Result { + let mut offset_in = self.offset_in; + let mut offset_out = self.offset_out; + let offset_in_ptr = if offset_in < 0 { + std::ptr::null_mut() + } else { + &mut offset_in + }; + let offset_out_ptr = if offset_out < 0 { + std::ptr::null_mut() + } else { + &mut offset_out + }; + Ok(syscall!(libc::splice( + self.fd_in.as_fd().as_raw_fd(), + offset_in_ptr, + self.fd_out.as_fd().as_raw_fd(), + offset_out_ptr, + self.len, + self.flags, + ))? as _) + } } mod buf_ring { diff --git a/compio-driver/src/sys/poll/op.rs b/compio-driver/src/sys/poll/op.rs index c1e5c487..9281a181 100644 --- a/compio-driver/src/sys/poll/op.rs +++ b/compio-driver/src/sys/poll/op.rs @@ -10,10 +10,6 @@ use std::{ }; use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut}; -#[cfg(not(gnulinux))] -use libc::open; -#[cfg(gnulinux)] -use libc::open64 as open; #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "hurd")))] use libc::{pread, preadv, pwrite, pwritev}; #[cfg(any(target_os = "linux", target_os = "android", target_os = "hurd"))] @@ -74,11 +70,7 @@ unsafe impl OpCode for OpenFile { } fn operate(self: Pin<&mut Self>) -> Poll> { - Poll::Ready(Ok(syscall!(open( - self.path.as_ptr(), - self.flags | libc::O_CLOEXEC, - self.mode as libc::c_int - ))? as _)) + Poll::Ready(self.call()) } } @@ -88,7 +80,7 @@ unsafe impl OpCode for CloseFile { } fn operate(self: Pin<&mut Self>) -> Poll> { - Poll::Ready(Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)) + Poll::Ready(self.call()) } } @@ -98,7 +90,7 @@ unsafe impl OpCode for TruncateFile { } fn operate(self: Pin<&mut Self>) -> Poll> { - Poll::Ready(self.truncate()) + Poll::Ready(self.call()) } } @@ -532,12 +524,7 @@ unsafe impl OpCode for Unlink { } fn operate(self: Pin<&mut Self>) -> Poll> { - if self.dir { - syscall!(libc::rmdir(self.path.as_ptr()))?; - } else { - syscall!(libc::unlink(self.path.as_ptr()))?; - } - Poll::Ready(Ok(0)) + Poll::Ready(self.call()) } } @@ -547,8 +534,7 @@ unsafe impl OpCode for CreateDir { } fn operate(self: Pin<&mut Self>) -> Poll> { - syscall!(libc::mkdir(self.path.as_ptr(), self.mode))?; - Poll::Ready(Ok(0)) + Poll::Ready(self.call()) } } @@ -558,8 +544,7 @@ unsafe impl OpCode for Rename { } fn operate(self: Pin<&mut Self>) -> Poll> { - syscall!(libc::rename(self.old_path.as_ptr(), self.new_path.as_ptr()))?; - Poll::Ready(Ok(0)) + Poll::Ready(self.call()) } } @@ -569,8 +554,7 @@ unsafe impl OpCode for Symlink { } fn operate(self: Pin<&mut Self>) -> Poll> { - syscall!(libc::symlink(self.source.as_ptr(), self.target.as_ptr()))?; - Poll::Ready(Ok(0)) + Poll::Ready(self.call()) } } @@ -580,8 +564,7 @@ unsafe impl OpCode for HardLink { } fn operate(self: Pin<&mut Self>) -> Poll> { - syscall!(libc::link(self.source.as_ptr(), self.target.as_ptr()))?; - Poll::Ready(Ok(0)) + Poll::Ready(self.call()) } } @@ -661,9 +644,7 @@ unsafe impl OpCode for ShutdownSocket { } fn operate(self: Pin<&mut Self>) -> Poll> { - Poll::Ready(Ok( - syscall!(libc::shutdown(self.fd.as_fd().as_raw_fd(), self.how()))? as _, - )) + Poll::Ready(self.call()) } } @@ -673,7 +654,7 @@ unsafe impl OpCode for CloseSocket { } fn operate(self: Pin<&mut Self>) -> Poll> { - Poll::Ready(Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)) + Poll::Ready(self.call()) } } @@ -1245,15 +1226,15 @@ unsafe impl OpCode for Splice { } else { &mut offset_out }; - // We don't wait for `fd_out` here. It's users' responsibility to ensure it's - // writable. - Poll::Ready(Ok(syscall!(libc::splice( - self.fd_in.as_fd().as_raw_fd(), - offset_in_ptr, - self.fd_out.as_fd().as_raw_fd(), - offset_out_ptr, - self.len, - self.flags as _, - ))? as _)) + syscall!( + break libc::splice( + self.fd_in.as_fd().as_raw_fd(), + offset_in_ptr, + self.fd_out.as_fd().as_raw_fd(), + offset_out_ptr, + self.len, + self.flags | libc::SPLICE_F_NONBLOCK, + ) + ) } } diff --git a/compio-driver/src/sys/unix_op.rs b/compio-driver/src/sys/unix_op.rs index 271bb17b..5da6b3dd 100644 --- a/compio-driver/src/sys/unix_op.rs +++ b/compio-driver/src/sys/unix_op.rs @@ -1,5 +1,6 @@ use std::{ ffi::CString, + io, marker::PhantomPinned, net::Shutdown, os::fd::{AsFd, AsRawFd, OwnedFd}, @@ -7,6 +8,10 @@ use std::{ }; use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut}; +#[cfg(not(gnulinux))] +use libc::open; +#[cfg(gnulinux)] +use libc::open64 as open; #[cfg(not(any( all(target_os = "linux", not(target_env = "musl")), target_os = "android", @@ -24,7 +29,7 @@ use libc::{ftruncate64, off64_t}; use pin_project_lite::pin_project; use socket2::{SockAddr, SockAddrStorage, socklen_t}; -use crate::{op::*, sys::aio::*, sys_slice::*}; +use crate::{op::*, sys::aio::*, sys_slice::*, syscall}; /// Open or create a file with flags and mode. pub struct OpenFile { @@ -38,6 +43,20 @@ impl OpenFile { pub fn new(path: CString, flags: i32, mode: libc::mode_t) -> Self { Self { path, flags, mode } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(open( + self.path.as_ptr(), + self.flags | libc::O_CLOEXEC, + self.mode as libc::c_int + ))? as _) + } +} + +impl CloseFile { + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _) + } } #[derive(Debug)] @@ -54,11 +73,11 @@ impl TruncateFile { Self { fd, size } } - pub(crate) fn truncate(&self) -> std::io::Result { + pub(crate) fn call(&self) -> io::Result { let size: off64_t = self .size .try_into() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?; + .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; crate::syscall!(ftruncate64(self.fd.as_fd().as_raw_fd(), size)).map(|v| v as _) } } @@ -290,6 +309,14 @@ impl Unlink { pub fn new(path: CString, dir: bool) -> Self { Self { path, dir } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + if self.dir { + Ok(syscall!(libc::rmdir(self.path.as_ptr()))? as _) + } else { + Ok(syscall!(libc::unlink(self.path.as_ptr()))? as _) + } + } } /// Create a directory. @@ -303,6 +330,10 @@ impl CreateDir { pub fn new(path: CString, mode: libc::mode_t) -> Self { Self { path, mode } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::mkdir(self.path.as_ptr(), self.mode))? as _) + } } /// Rename a file or directory. @@ -316,6 +347,10 @@ impl Rename { pub fn new(old_path: CString, new_path: CString) -> Self { Self { old_path, new_path } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::rename(self.old_path.as_ptr(), self.new_path.as_ptr()))? as _) + } } /// Create a symlink. @@ -329,6 +364,10 @@ impl Symlink { pub fn new(source: CString, target: CString) -> Self { Self { source, target } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::symlink(self.source.as_ptr(), self.target.as_ptr()))? as _) + } } /// Create a hard link. @@ -342,6 +381,10 @@ impl HardLink { pub fn new(source: CString, target: CString) -> Self { Self { source, target } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::link(self.source.as_ptr(), self.target.as_ptr()))? as _) + } } /// Create a socket. @@ -362,7 +405,7 @@ impl CreateSocket { } } -impl ShutdownSocket { +impl ShutdownSocket { pub(crate) fn how(&self) -> i32 { match self.how { Shutdown::Write => libc::SHUT_WR, @@ -370,6 +413,16 @@ impl ShutdownSocket { Shutdown::Both => libc::SHUT_RDWR, } } + + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::shutdown(self.fd.as_fd().as_raw_fd(), self.how()))? as _) + } +} + +impl CloseSocket { + pub(crate) fn call(self: Pin<&mut Self>) -> io::Result { + Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _) + } } pin_project! { From 2832552505c8f61160bb0fa8f86ef97f98ebbe35 Mon Sep 17 00:00:00 2001 From: Yuyi Wang Date: Thu, 29 Jan 2026 22:24:46 +0800 Subject: [PATCH 2/2] docs: add changelog entry --- compio-driver/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/compio-driver/CHANGELOG.md b/compio-driver/CHANGELOG.md index 9f5fe245..398236e9 100644 --- a/compio-driver/CHANGELOG.md +++ b/compio-driver/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- *(driver)* [**breaking**] full iour fallback ([#656](https://github.com/compio-rs/compio/pull/656)) - *(runtime)* future combinator ([#639](https://github.com/compio-rs/compio/pull/639)) - *(fs)* splice ([#635](https://github.com/compio-rs/compio/pull/635)) - *(driver)* fake splice test ([#638](https://github.com/compio-rs/compio/pull/638))