From 112c268cd79438caae20a0bd4560ada5a1565450 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 8 Oct 2023 21:18:02 -0700 Subject: [PATCH] io-uring API updates. (#871) * io-uring API updates. Add the `addr_len` field to `splice_fd_in_or_file_index_union`, define the `io_uring_sync_cancel_reg` struct, and export the various flags types used in the public API from the `io_uring` module so that users don't need to enable "fs" or "net" themselves just to work with `io_uring`. * Make `Nsecs` be 64-bit on 32-bit x86 Linux. --- src/backend/libc/fs/syscalls.rs | 24 ++++++++++++--- src/io_uring.rs | 52 ++++++++++++++++++++++++--------- src/timespec.rs | 25 +++++++++------- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 8a3a55d2e..692bd4eb2 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -933,7 +933,11 @@ fn utimensat_old( .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times.last_access.tv_nsec, + tv_nsec: times + .last_access + .tv_nsec + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, }, c::timespec { tv_sec: times @@ -941,7 +945,11 @@ fn utimensat_old( .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times.last_modification.tv_nsec, + tv_nsec: times + .last_modification + .tv_nsec + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, }, ]; unsafe { @@ -1515,7 +1523,11 @@ fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> { .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times.last_access.tv_nsec, + tv_nsec: times + .last_access + .tv_nsec + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, }, c::timespec { tv_sec: times @@ -1523,7 +1535,11 @@ fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> { .tv_sec .try_into() .map_err(|_| io::Errno::OVERFLOW)?, - tv_nsec: times.last_modification.tv_nsec, + tv_nsec: times + .last_modification + .tv_nsec + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, }, ]; diff --git a/src/io_uring.rs b/src/io_uring.rs index 09a4d6d62..c166e747a 100644 --- a/src/io_uring.rs +++ b/src/io_uring.rs @@ -31,6 +31,11 @@ use core::mem::MaybeUninit; use core::ptr::{null_mut, write_bytes}; use linux_raw_sys::net; +// Export types used in io_uring APIs. +pub use crate::fs::{Advice, AtFlags, OFlags, RenameFlags, ResolveFlags, Statx}; +pub use crate::net::{RecvFlags, SendFlags, SocketFlags}; +pub use crate::timespec::Timespec; + mod sys { pub(super) use linux_raw_sys::io_uring::*; #[cfg(test)] @@ -1062,20 +1067,20 @@ pub union op_flags_union { pub sync_range_flags: u32, /// `msg_flags` is split into `send_flags` and `recv_flags`. #[doc(alias = "msg_flags")] - pub send_flags: crate::net::SendFlags, + pub send_flags: SendFlags, /// `msg_flags` is split into `send_flags` and `recv_flags`. #[doc(alias = "msg_flags")] - pub recv_flags: crate::net::RecvFlags, + pub recv_flags: RecvFlags, pub timeout_flags: IoringTimeoutFlags, - pub accept_flags: crate::net::SocketFlags, + pub accept_flags: SocketFlags, pub cancel_flags: IoringAsyncCancelFlags, - pub open_flags: crate::fs::OFlags, - pub statx_flags: crate::fs::AtFlags, - pub fadvise_advice: crate::fs::Advice, + pub open_flags: OFlags, + pub statx_flags: AtFlags, + pub fadvise_advice: Advice, pub splice_flags: SpliceFlags, - pub rename_flags: crate::fs::RenameFlags, - pub unlink_flags: crate::fs::AtFlags, - pub hardlink_flags: crate::fs::AtFlags, + pub rename_flags: RenameFlags, + pub unlink_flags: AtFlags, + pub hardlink_flags: AtFlags, pub msg_ring_flags: IoringMsgringFlags, } @@ -1087,12 +1092,33 @@ pub union buf_union { pub buf_group: u16, } +// TODO: Rename this to include `addr_len` when we have a semver bump? #[allow(missing_docs)] #[repr(C)] #[derive(Copy, Clone)] pub union splice_fd_in_or_file_index_union { pub splice_fd_in: i32, pub file_index: u32, + pub addr_len: addr_len_struct, +} + +#[allow(missing_docs)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct addr_len_struct { + pub addr_len: u16, + pub __pad3: [u16; 1], +} + +#[allow(missing_docs)] +#[repr(C)] +#[derive(Copy, Clone)] +pub struct io_uring_sync_cancel_reg { + pub addr: u64, + pub fd: i32, + pub flags: IoringAsyncCancelFlags, + pub timeout: Timespec, + pub pad: [u64; 4], } /// An io_uring Completion Queue Entry. @@ -1269,16 +1295,12 @@ pub struct iovec { #[derive(Debug, Copy, Clone, Default)] pub struct open_how { /// An [`OFlags`] value represented as a `u64`. - /// - /// [`OFlags`]: crate::fs::OFlags pub flags: u64, /// A [`Mode`] value represented as a `u64`. - /// - /// [`Mode`]: crate::fs::Mode pub mode: u64, - pub resolve: crate::fs::ResolveFlags, + pub resolve: ResolveFlags, } #[allow(missing_docs)] @@ -1377,6 +1399,7 @@ fn io_uring_layouts() { check_renamed_type!(op_flags_union, io_uring_sqe__bindgen_ty_3); check_renamed_type!(buf_union, io_uring_sqe__bindgen_ty_4); check_renamed_type!(splice_fd_in_or_file_index_union, io_uring_sqe__bindgen_ty_5); + check_renamed_type!(addr_len_struct, io_uring_sqe__bindgen_ty_5__bindgen_ty_1); check_renamed_type!( register_or_sqe_op_or_sqe_flags_union, io_uring_restriction__bindgen_ty_1 @@ -1460,4 +1483,5 @@ fn io_uring_layouts() { check_struct!(open_how, flags, mode, resolve); check_struct!(io_uring_buf_reg, ring_addr, ring_entries, bgid, pad, resv); check_struct!(io_uring_buf, addr, len, bid, resv); + check_struct!(io_uring_sync_cancel_reg, addr, fd, flags, timeout, pad); } diff --git a/src/timespec.rs b/src/timespec.rs index 51c2d2443..a2df0e7b9 100644 --- a/src/timespec.rs +++ b/src/timespec.rs @@ -1,6 +1,7 @@ //! `Timespec` and related types, which are used by multiple public API //! modules. +#[cfg(not(fix_y2038))] use crate::backend::c; /// `struct timespec` @@ -28,18 +29,22 @@ pub type Secs = c::time_t; #[cfg(fix_y2038)] pub type Secs = i64; -/// A type for the `tv_nsec` field of [`Timespec`]. -#[cfg(all(libc, target_arch = "x86_64", target_pointer_width = "32"))] +/// A type for the `tv_sec` field of [`Timespec`]. +#[cfg(any( + fix_y2038, + linux_raw, + all(libc, target_arch = "x86_64", target_pointer_width = "32") +))] pub type Nsecs = i64; /// A type for the `tv_nsec` field of [`Timespec`]. -#[cfg(all(libc, not(all(target_arch = "x86_64", target_pointer_width = "32"))))] +#[cfg(all( + not(fix_y2038), + libc, + not(all(target_arch = "x86_64", target_pointer_width = "32")) +))] pub type Nsecs = c::c_long; -/// A type for the `tv_nsec` field of [`Timespec`]. -#[cfg(linux_raw)] -pub type Nsecs = i64; - /// On 32-bit glibc platforms, `timespec` has anonymous padding fields, which /// Rust doesn't support yet (see `unnamed_fields`), so we define our own /// struct with explicit padding, with bidirectional `From` impls. @@ -52,7 +57,7 @@ pub(crate) struct LibcTimespec { #[cfg(target_endian = "big")] padding: core::mem::MaybeUninit, - pub(crate) tv_nsec: Nsecs, + pub(crate) tv_nsec: i32, #[cfg(target_endian = "little")] padding: core::mem::MaybeUninit, @@ -64,7 +69,7 @@ impl From for Timespec { fn from(t: LibcTimespec) -> Self { Self { tv_sec: t.tv_sec, - tv_nsec: t.tv_nsec, + tv_nsec: t.tv_nsec as _, } } } @@ -75,7 +80,7 @@ impl From for LibcTimespec { fn from(t: Timespec) -> Self { Self { tv_sec: t.tv_sec, - tv_nsec: t.tv_nsec, + tv_nsec: t.tv_nsec as _, padding: core::mem::MaybeUninit::uninit(), } }