Skip to content

Commit

Permalink
Fixes needed by io_uring. (#873)
Browse files Browse the repository at this point in the history
* Fixes needed by io_uring.

 - Have the `io_uring` module export more types used in opcode entries.
 - Define a conversion from `SocketAddr` to `SocketAddrAny`.
 - Add comments to the `fadvise` implementation.

* Pin regex to 1.9 in Rust 1.63 builds.

* Make more `Epoll` types available to io_uring too.

This enables most of the epoll module without needing "alloc". It
doesn't enable `epoll_wait`, because that needs `Vec`, but this
does potentially open up a path to having a non-allocating opetion
for waiting on an epoll.
  • Loading branch information
sunfishcode committed Oct 10, 2023
1 parent 5e5c046 commit d012bcf
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 21 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
if: matrix.rust == '1.63'
run: |
cargo update --package=dashmap --precise 5.4.0
cargo update --package=regex --precise=1.9.0
- run: >
rustup target add
Expand Down Expand Up @@ -481,6 +482,7 @@ jobs:
if: matrix.rust == '1.63'
run: |
cargo update --package=dashmap --precise 5.4.0
cargo update --package=regex --precise=1.9.0
- run: |
cargo test --verbose --features=all-apis --release --workspace -- --nocapture
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ event = []
fs = []

# Enable `rustix::io_uring::*` (on platforms that support it).
io_uring = ["fs", "net", "linux-raw-sys/io_uring"]
io_uring = ["event", "fs", "net", "linux-raw-sys/io_uring"]

# Enable `rustix::mount::*`.
mount = []
Expand Down
10 changes: 9 additions & 1 deletion src/backend/libc/event/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,13 @@
//! ```

use crate::backend::c;
use crate::backend::conv::{ret, ret_owned_fd, ret_u32};
#[cfg(feature = "alloc")]
use crate::backend::conv::ret_u32;
use crate::backend::conv::{ret, ret_owned_fd};
use crate::fd::{AsFd, AsRawFd, OwnedFd};
use crate::io;
use crate::utils::as_mut_ptr;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use bitflags::bitflags;
use core::ffi::c_void;
Expand Down Expand Up @@ -257,6 +260,8 @@ pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
///
/// For each event of interest, an element is written to `events`. On
/// success, this returns the number of written elements.
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
// SAFETY: We're calling `epoll_wait` via FFI and we know how it
// behaves.
Expand Down Expand Up @@ -395,10 +400,12 @@ struct SixtyFourBitPointer {
}

/// A vector of `Event`s, plus context for interpreting them.
#[cfg(feature = "alloc")]
pub struct EventVec {
events: Vec<Event>,
}

#[cfg(feature = "alloc")]
impl EventVec {
/// Constructs an `EventVec` from raw pointer, length, and capacity.
///
Expand Down Expand Up @@ -473,6 +480,7 @@ impl EventVec {
}
}

#[cfg(feature = "alloc")]
impl<'a> IntoIterator for &'a EventVec {
type IntoIter = Iter<'a>;
type Item = Event;
Expand Down
2 changes: 1 addition & 1 deletion src/backend/libc/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ pub(crate) mod types;
#[cfg_attr(windows, path = "windows_syscalls.rs")]
pub(crate) mod syscalls;

#[cfg(all(feature = "alloc", linux_kernel))]
#[cfg(linux_kernel)]
pub mod epoll;
2 changes: 1 addition & 1 deletion src/backend/linux_raw/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> {
}
}

#[cfg(all(feature = "alloc", feature = "event"))]
#[cfg(feature = "event")]
impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> {
#[inline]
fn from(flags: crate::event::epoll::CreateFlags) -> Self {
Expand Down
6 changes: 6 additions & 0 deletions src/backend/linux_raw/event/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ use crate::backend::c;
use crate::backend::event::syscalls;
use crate::fd::{AsFd, AsRawFd, OwnedFd};
use crate::io;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use bitflags::bitflags;
use core::ffi::c_void;
Expand Down Expand Up @@ -242,6 +243,8 @@ pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
///
/// For each event of interest, an element is written to `events`. On
/// success, this returns the number of written elements.
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
#[inline]
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
// SAFETY: We're calling `epoll_wait` via FFI and we know how it
Expand Down Expand Up @@ -371,10 +374,12 @@ struct SixtyFourBitPointer {
}

/// A vector of `Event`s, plus context for interpreting them.
#[cfg(feature = "alloc")]
pub struct EventVec {
events: Vec<Event>,
}

#[cfg(feature = "alloc")]
impl EventVec {
/// Constructs an `EventVec` from raw pointer, length, and capacity.
///
Expand Down Expand Up @@ -449,6 +454,7 @@ impl EventVec {
}
}

#[cfg(feature = "alloc")]
impl<'a> IntoIterator for &'a EventVec {
type IntoIter = Iter<'a>;
type Item = Event;
Expand Down
1 change: 0 additions & 1 deletion src/backend/linux_raw/event/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#[cfg(feature = "alloc")]
pub mod epoll;
pub(crate) mod poll_fd;
pub(crate) mod syscalls;
Expand Down
20 changes: 7 additions & 13 deletions src/backend/linux_raw/event/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]

use crate::backend::c;
use crate::backend::conv::{c_int, c_uint, ret_owned_fd, ret_usize, slice_mut};
use crate::event::{EventfdFlags, PollFd};
use crate::fd::OwnedFd;
use crate::io;
#[cfg(feature = "alloc")]
use {
crate::backend::conv::{by_ref, pass_usize, raw_fd, ret, zero},
crate::event::epoll,
crate::fd::BorrowedFd,
linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD},
use crate::backend::conv::pass_usize;
use crate::backend::conv::{
by_ref, c_int, c_uint, raw_fd, ret, ret_owned_fd, ret_usize, slice_mut, zero,
};
use crate::event::{epoll, EventfdFlags, PollFd};
use crate::fd::{BorrowedFd, OwnedFd};
use crate::io;
use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
use {
crate::backend::conv::{opt_ref, size_of},
Expand Down Expand Up @@ -52,13 +50,11 @@ pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usiz
}
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) unsafe fn epoll_add(
epfd: BorrowedFd<'_>,
Expand All @@ -74,7 +70,6 @@ pub(crate) unsafe fn epoll_add(
))
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) unsafe fn epoll_mod(
epfd: BorrowedFd<'_>,
Expand All @@ -90,7 +85,6 @@ pub(crate) unsafe fn epoll_mod(
))
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> {
ret(syscall_readonly!(
Expand Down
6 changes: 6 additions & 0 deletions src/backend/linux_raw/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) ->
lo(len)
))
}

// On mips, the arguments are not reordered, and padding is inserted
// instead to ensure alignment.
#[cfg(any(target_arch = "mips", target_arch = "mips32r6"))]
Expand All @@ -393,6 +394,9 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) ->
advice
))
}

// For all other 32-bit architectures, use `fadvise64_64` so that we get a
// 64-bit length.
#[cfg(all(
target_pointer_width = "32",
not(any(
Expand All @@ -413,6 +417,8 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, pos: u64, len: u64, advice: Advice) ->
advice
))
}

// On 64-bit architectures, use `fadvise64` which is sufficient.
#[cfg(target_pointer_width = "64")]
unsafe {
ret(syscall_readonly!(
Expand Down
2 changes: 1 addition & 1 deletion src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod poll;
#[cfg(solarish)]
pub mod port;

#[cfg(all(feature = "alloc", linux_kernel))]
#[cfg(linux_kernel)]
pub use crate::backend::event::epoll;
#[cfg(any(
linux_kernel,
Expand Down
42 changes: 41 additions & 1 deletion src/io_uring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,47 @@ 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::event::epoll::{
Event as EpollEvent, EventData as EpollEventData, EventFlags as EpollEventFlags,
};
pub use crate::fs::{Advice, AtFlags, Mode, OFlags, RenameFlags, ResolveFlags, Statx, StatxFlags};
pub use crate::io::ReadWriteFlags;
pub use crate::net::{RecvFlags, SendFlags, SocketFlags};
pub use crate::timespec::Timespec;
pub use linux_raw_sys::general::sigset_t;

pub use net::{__kernel_sockaddr_storage as sockaddr_storage, msghdr, sockaddr, socklen_t};

// Declare the `c_char` type for use with entries that take pointers
// to C strings. Define it as unsigned or signed according to the platform
// so that we match what Rust's `CStr` uses.
//
// When we can update to linux-raw-sys 0.5, we can remove this, as its
// `c_char` type will declare this.
/// The C `char` type.
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "msp430",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "s390x",
))]
#[allow(non_camel_case_types)]
pub type c_char = u8;
/// The C `char` type.
#[cfg(any(
target_arch = "mips",
target_arch = "mips64",
target_arch = "sparc64",
target_arch = "x86",
target_arch = "x86_64",
target_arch = "xtensa",
))]
#[allow(non_camel_case_types)]
pub type c_char = i8;

mod sys {
pub(super) use linux_raw_sys::io_uring::*;
Expand Down Expand Up @@ -1393,6 +1431,8 @@ impl Default for register_or_sqe_op_or_sqe_flags_union {
fn io_uring_layouts() {
use sys as c;

assert_eq_size!(io_uring_ptr, u64);

check_renamed_type!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1);
check_renamed_type!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2);
check_renamed_type!(addr3_or_cmd_union, io_uring_sqe__bindgen_ty_6);
Expand Down
12 changes: 11 additions & 1 deletion src/net/socket_addr_any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#[cfg(unix)]
use crate::net::SocketAddrUnix;
use crate::net::{AddressFamily, SocketAddrV4, SocketAddrV6};
use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::{backend, io};
#[cfg(feature = "std")]
use core::fmt;
Expand All @@ -32,6 +32,16 @@ pub enum SocketAddrAny {
Unix(SocketAddrUnix),
}

impl From<SocketAddr> for SocketAddrAny {
#[inline]
fn from(from: SocketAddr) -> Self {
match from {
SocketAddr::V4(v4) => Self::V4(v4),
SocketAddr::V6(v6) => Self::V6(v6),
}
}
}

impl From<SocketAddrV4> for SocketAddrAny {
#[inline]
fn from(from: SocketAddrV4) -> Self {
Expand Down

0 comments on commit d012bcf

Please sign in to comment.