Skip to content

Commit da8342c

Browse files
authored
Hide resv fields in io_uring. (#1370)
Users are not supposed to touch `resv` fields, so make them `doc(hidden)` and make structs containing them `non_exhaustive`. Also, add a `const` constructor for `io_uring_user_data`.
1 parent 6cd4a06 commit da8342c

File tree

4 files changed

+68
-31
lines changed

4 files changed

+68
-31
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ jobs:
5555
cargo update --package=regex --precise=1.9.0
5656
cargo update --package=half --precise=2.2.1
5757
cargo update --package=flate2 --precise=1.0.35
58+
cargo update --package=textwrap --precise=0.16.1
5859
5960
- run: >
6061
rustup target add
@@ -529,6 +530,7 @@ jobs:
529530
cargo update --package=regex --precise=1.9.0
530531
cargo update --package=half --precise=2.2.1
531532
cargo update --package=flate2 --precise=1.0.35
533+
cargo update --package=textwrap --precise=0.16.1
532534
533535
- run: |
534536
cargo test --verbose --features=all-apis --release --workspace -- --nocapture

CHANGES.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ constant.
5757
[`IORING_REGISTER_FILES_SKIP`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/constant.IORING_REGISTER_FILES_SKIP.html
5858
[`rustix::fs::CWD`]: https://docs.rs/rustix/1.0.0/rustix/fs/constant.CWD.html
5959

60+
[`rustix::io_uring::io_uring_register`] now has a [`IoringRegisterFlags`]
61+
argument, and `rustix::io_uring::io_uring_register_with` is removed.
62+
63+
[`rustix::io_uring::io_uring_register`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/fn.io_uring_register.html
64+
[`IoringRegisterFlags`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/struct.IoringRegisterFlags.html
65+
66+
Several structs in [`rustix::io_uring`] are now marked `#[non_exhaustive]`
67+
because they contain padding or reserved fields. Instead of constructing
68+
them with field values and `..Default::default()`, construct them with
69+
`Default::default()` and separately assign the fields.
70+
71+
[`rustix::io_uring`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/index.html
72+
6073
`rustix::process::WaitidOptions` and `rustix::process::WaitidStatus` are
6174
renamed to
6275
[`rustix::process::WaitIdOptions`] and [`rustix::process::WaitIdStatus`] (note
@@ -156,12 +169,6 @@ from the number of bytes written to the buffer when
156169
[`rustix::net::recvfrom`]: https://docs.rs/rustix/1.0.0/rustix/net/fn.recvfrom.html
157170
[`rustix::net::RecvFlags::TRUNC`]: https://docs.rs/rustix/1.0.0/rustix/net/struct.RecvFlags.html#associatedconstant.TRUNC
158171

159-
[`rustix::io_uring::io_uring_register`] now has a [`IoringRegisterFlags`]
160-
argument, and `rustix::io_uring::io_uring_register_with` is removed.
161-
162-
[`rustix::io_uring::io_uring_register`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/fn.io_uring_register.html
163-
[`IoringRegisterFlags`]: https://docs.rs/rustix/1.0.0/rustix/io_uring/struct.IoringRegisterFlags.html
164-
165172
[`rustix::process::Signal`] constants are now upper-cased; for example,
166173
`Signal::Int` is now named [`Signal::INT`]. Also, `Signal` is no longer
167174
directly convertible to `i32`; use [`Signal::as_raw`] instead.

src/io_uring/mod.rs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use bindgen_types::*;
3333
use core::cmp::Ordering;
3434
use core::ffi::c_void;
3535
use core::hash::{Hash, Hasher};
36-
use core::mem::{size_of, MaybeUninit};
37-
use core::ptr::{null_mut, write_bytes};
36+
use core::mem::size_of;
37+
use core::ptr::null_mut;
3838
use linux_raw_sys::net;
3939

4040
// Export types used in io_uring APIs.
@@ -1155,6 +1155,13 @@ pub union io_uring_user_data {
11551155
}
11561156

11571157
impl io_uring_user_data {
1158+
/// Create a zero-initialized `Self`.
1159+
pub const fn zeroed() -> Self {
1160+
// Initialize the `u64_` field, which is the size of the full union.
1161+
// This can use `core::mem::zeroed` in Rust 1.75.
1162+
Self { u64_: 0 }
1163+
}
1164+
11581165
/// Return the `u64` value.
11591166
#[inline]
11601167
pub const fn u64_(self) -> u64 {
@@ -1236,12 +1243,7 @@ impl Hash for io_uring_user_data {
12361243
impl Default for io_uring_user_data {
12371244
#[inline]
12381245
fn default() -> Self {
1239-
let mut s = MaybeUninit::<Self>::uninit();
1240-
// SAFETY: All of Linux's io_uring structs may be zero-initialized.
1241-
unsafe {
1242-
write_bytes(s.as_mut_ptr(), 0, 1);
1243-
s.assume_init()
1244-
}
1246+
Self::zeroed()
12451247
}
12461248
}
12471249

@@ -1449,10 +1451,13 @@ pub struct io_uring_cqe {
14491451
#[allow(missing_docs)]
14501452
#[repr(C)]
14511453
#[derive(Copy, Clone, Default)]
1454+
#[non_exhaustive]
14521455
pub struct io_uring_restriction {
14531456
pub opcode: IoringRestrictionOp,
14541457
pub register_or_sqe_op_or_sqe_flags: register_or_sqe_op_or_sqe_flags_union,
1458+
#[doc(hidden)]
14551459
pub resv: u8,
1460+
#[doc(hidden)]
14561461
pub resv2: [u32; 3],
14571462
}
14581463

@@ -1468,6 +1473,7 @@ pub union register_or_sqe_op_or_sqe_flags_union {
14681473
#[allow(missing_docs)]
14691474
#[repr(C)]
14701475
#[derive(Debug, Copy, Clone, Default)]
1476+
#[non_exhaustive]
14711477
pub struct io_uring_params {
14721478
pub sq_entries: u32,
14731479
pub cq_entries: u32,
@@ -1476,6 +1482,7 @@ pub struct io_uring_params {
14761482
pub sq_thread_idle: u32,
14771483
pub features: IoringFeatureFlags,
14781484
pub wq_fd: RawFd,
1485+
#[doc(hidden)]
14791486
pub resv: [u32; 3],
14801487
pub sq_off: io_sqring_offsets,
14811488
pub cq_off: io_cqring_offsets,
@@ -1484,6 +1491,7 @@ pub struct io_uring_params {
14841491
#[allow(missing_docs)]
14851492
#[repr(C)]
14861493
#[derive(Debug, Copy, Clone, Default)]
1494+
#[non_exhaustive]
14871495
pub struct io_sqring_offsets {
14881496
pub head: u32,
14891497
pub tail: u32,
@@ -1492,13 +1500,15 @@ pub struct io_sqring_offsets {
14921500
pub flags: u32,
14931501
pub dropped: u32,
14941502
pub array: u32,
1503+
#[doc(hidden)]
14951504
pub resv1: u32,
14961505
pub user_addr: io_uring_ptr,
14971506
}
14981507

14991508
#[allow(missing_docs)]
15001509
#[repr(C)]
15011510
#[derive(Debug, Copy, Clone, Default)]
1511+
#[non_exhaustive]
15021512
pub struct io_cqring_offsets {
15031513
pub head: u32,
15041514
pub tail: u32,
@@ -1507,46 +1517,57 @@ pub struct io_cqring_offsets {
15071517
pub overflow: u32,
15081518
pub cqes: u32,
15091519
pub flags: u32,
1520+
#[doc(hidden)]
15101521
pub resv1: u32,
15111522
pub user_addr: io_uring_ptr,
15121523
}
15131524

15141525
#[allow(missing_docs)]
15151526
#[repr(C)]
15161527
#[derive(Debug, Default)]
1528+
#[non_exhaustive]
15171529
pub struct io_uring_probe {
15181530
pub last_op: IoringOp,
15191531
pub ops_len: u8,
1532+
#[doc(hidden)]
15201533
pub resv: u16,
1534+
#[doc(hidden)]
15211535
pub resv2: [u32; 3],
15221536
pub ops: IncompleteArrayField<io_uring_probe_op>,
15231537
}
15241538

15251539
#[allow(missing_docs)]
15261540
#[repr(C)]
15271541
#[derive(Debug, Copy, Clone, Default)]
1542+
#[non_exhaustive]
15281543
pub struct io_uring_probe_op {
15291544
pub op: IoringOp,
1545+
#[doc(hidden)]
15301546
pub resv: u8,
15311547
pub flags: IoringOpFlags,
1548+
#[doc(hidden)]
15321549
pub resv2: u32,
15331550
}
15341551

15351552
#[allow(missing_docs)]
15361553
#[repr(C, align(8))]
15371554
#[derive(Debug, Copy, Clone, Default)]
1555+
#[non_exhaustive]
15381556
pub struct io_uring_files_update {
15391557
pub offset: u32,
1558+
#[doc(hidden)]
15401559
pub resv: u32,
15411560
pub fds: io_uring_ptr,
15421561
}
15431562

15441563
#[allow(missing_docs)]
15451564
#[repr(C, align(8))]
15461565
#[derive(Debug, Copy, Clone, Default)]
1566+
#[non_exhaustive]
15471567
pub struct io_uring_rsrc_register {
15481568
pub nr: u32,
15491569
pub flags: IoringRsrcFlags,
1570+
#[doc(hidden)]
15501571
pub resv2: u64,
15511572
pub data: io_uring_ptr,
15521573
pub tags: io_uring_ptr,
@@ -1555,21 +1576,26 @@ pub struct io_uring_rsrc_register {
15551576
#[allow(missing_docs)]
15561577
#[repr(C, align(8))]
15571578
#[derive(Debug, Copy, Clone, Default)]
1579+
#[non_exhaustive]
15581580
pub struct io_uring_rsrc_update {
15591581
pub offset: u32,
1582+
#[doc(hidden)]
15601583
pub resv: u32,
15611584
pub data: io_uring_ptr,
15621585
}
15631586

15641587
#[allow(missing_docs)]
15651588
#[repr(C, align(8))]
15661589
#[derive(Debug, Copy, Clone, Default)]
1590+
#[non_exhaustive]
15671591
pub struct io_uring_rsrc_update2 {
15681592
pub offset: u32,
1593+
#[doc(hidden)]
15691594
pub resv: u32,
15701595
pub data: io_uring_ptr,
15711596
pub tags: io_uring_ptr,
15721597
pub nr: u32,
1598+
#[doc(hidden)]
15731599
pub resv2: u32,
15741600
}
15751601

@@ -1617,30 +1643,38 @@ pub struct open_how {
16171643
#[allow(missing_docs)]
16181644
#[repr(C)]
16191645
#[derive(Debug, Copy, Clone, Default)]
1646+
#[non_exhaustive]
16201647
pub struct io_uring_buf_reg {
16211648
pub ring_addr: io_uring_ptr,
16221649
pub ring_entries: u32,
16231650
pub bgid: u16,
16241651
pub flags: u16,
1652+
#[doc(hidden)]
16251653
pub resv: [u64; 3_usize],
16261654
}
16271655

16281656
#[allow(missing_docs)]
16291657
#[repr(C)]
16301658
#[derive(Debug, Copy, Clone, Default)]
1659+
#[non_exhaustive]
16311660
pub struct io_uring_buf {
16321661
pub addr: io_uring_ptr,
16331662
pub len: u32,
16341663
pub bid: u16,
1664+
#[doc(hidden)]
16351665
pub resv: u16,
16361666
}
16371667

16381668
#[allow(missing_docs)]
16391669
#[repr(C)]
16401670
#[derive(Debug, Copy, Clone, Default)]
1671+
#[non_exhaustive]
16411672
pub struct buf_ring_tail_struct {
1673+
#[doc(hidden)]
16421674
pub resv1: u64,
1675+
#[doc(hidden)]
16431676
pub resv2: u32,
1677+
#[doc(hidden)]
16441678
pub resv3: u16,
16451679
pub tail: u16,
16461680
}

tests/io_uring/register.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,9 @@ where
3535
}
3636

3737
fn register_ring(fd: BorrowedFd<'_>) -> Result<BorrowedFd<'_>> {
38-
let update = io_uring_rsrc_update {
39-
data: io_uring_ptr::new(fd.as_raw_fd() as u64 as *mut c_void),
40-
offset: u32::MAX,
41-
resv: 0,
42-
};
38+
let mut update = io_uring_rsrc_update::default();
39+
update.data = io_uring_ptr::new(fd.as_raw_fd() as usize as *mut c_void);
40+
update.offset = u32::MAX;
4341

4442
do_register(
4543
fd,
@@ -57,11 +55,9 @@ fn unregister_ring<FD>(fd: FD) -> Result<()>
5755
where
5856
FD: AsRawFd + AsFd,
5957
{
60-
let update = io_uring_rsrc_update {
61-
offset: fd.as_raw_fd() as u32,
62-
data: io_uring_ptr::null(),
63-
resv: 0,
64-
};
58+
let mut update = io_uring_rsrc_update::default();
59+
update.offset = fd.as_raw_fd() as u32;
60+
update.data = io_uring_ptr::null();
6561

6662
do_register(
6763
fd,
@@ -158,13 +154,11 @@ fn io_uring_buf_ring_can_be_registered() {
158154

159155
let br = unsafe { br_ptr.as_mut() }.expect("A valid io_uring_buf_ring struct");
160156

161-
let reg = io_uring_buf_reg {
162-
ring_addr: br_ptr.cast::<c_void>().into(),
163-
ring_entries: ENTRIES as u32,
164-
bgid: BGID,
165-
flags: 0,
166-
resv: [0_u64; 3],
167-
};
157+
let mut reg = io_uring_buf_reg::default();
158+
reg.ring_addr = br_ptr.cast::<c_void>().into();
159+
reg.ring_entries = ENTRIES as u32;
160+
reg.bgid = BGID;
161+
reg.flags = 0;
168162

169163
assert_eq!(register_buf_ring(ring_fd, &reg), Ok(()));
170164

0 commit comments

Comments
 (0)