Skip to content

Commit a96a854

Browse files
committed
Add ops {ReadvFixed, WritevFixed}
1 parent 267f229 commit a96a854

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

io-uring-test/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ fn test<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
116116
tests::fs::test_fixed_fd_install(&mut ring, &test)?;
117117
tests::fs::test_get_set_xattr(&mut ring, &test)?;
118118
tests::fs::test_f_get_set_xattr(&mut ring, &test)?;
119+
tests::fs::test_pipe_fixed_writev_readv(&mut ring, &test)?;
119120

120121
// timeout
121122
tests::timeout::test_timeout(&mut ring, &test)?;

io-uring-test/src/tests/fs.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::tests::register_buf_ring;
22
use crate::utils;
33
use crate::Test;
4+
use ::rustix::io_uring::iovec;
45
use ::std::collections::BTreeSet;
56
use io_uring::Errno;
67
use io_uring::{cqueue, opcode, squeue, types, IoUring};
@@ -249,6 +250,111 @@ pub fn test_file_writev_readv<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
249250
Ok(())
250251
}
251252

253+
pub fn test_pipe_fixed_writev_readv<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
254+
ring: &mut IoUring<S, C>,
255+
test: &Test,
256+
) -> anyhow::Result<()> {
257+
require!(
258+
test;
259+
test.probe.is_supported(opcode::WritevFixed::CODE);
260+
test.probe.is_supported(opcode::ReadvFixed::CODE);
261+
);
262+
263+
println!("test pipe_fixed_writev_readv");
264+
265+
ring.submitter().unregister_buffers()?;
266+
267+
let (rx, tx) = ::rustix::pipe::pipe()?;
268+
269+
const BYTES0: &[u8] = "The quick brown fox jumps over the lazy dog.".as_bytes();
270+
const BYTES1: &[u8] = "我能吞下玻璃而不伤身体。".as_bytes();
271+
272+
let mut src = Vec::with_capacity(BYTES0.len() + BYTES1.len());
273+
src.extend_from_slice(BYTES0);
274+
src.extend_from_slice(BYTES1);
275+
276+
let mut dst = vec![0u8; BYTES0.len() + BYTES1.len()];
277+
278+
unsafe {
279+
ring.submitter().register_buffers(&[
280+
iovec {
281+
iov_base: src.as_mut_ptr() as *mut _,
282+
iov_len: src.len(),
283+
},
284+
iovec {
285+
iov_base: dst.as_mut_ptr() as *mut _,
286+
iov_len: dst.len(),
287+
},
288+
])?;
289+
}
290+
291+
let src_parts = [
292+
libc::iovec {
293+
iov_base: src.as_ptr() as *mut _,
294+
iov_len: BYTES0.len(),
295+
},
296+
libc::iovec {
297+
iov_base: unsafe { src.as_ptr().add(BYTES0.len()) } as *mut _,
298+
iov_len: BYTES1.len(),
299+
},
300+
];
301+
unsafe {
302+
ring.submission().push(
303+
&opcode::WritevFixed::new(
304+
types::Fd(tx.as_raw_fd()),
305+
src_parts.as_ptr().cast(),
306+
src_parts.len() as u32,
307+
0,
308+
)
309+
.build()
310+
.user_data(0x666)
311+
.into(),
312+
)?;
313+
}
314+
ring.submit_and_wait(1)?;
315+
for cqe in ring.completion().map(Into::<cqueue::Entry>::into) {
316+
assert_eq!(cqe.user_data_u64(), 0x666);
317+
let len = cqe.result()?;
318+
assert_eq!(len, src.len() as _);
319+
}
320+
321+
let dst_parts = [
322+
libc::iovec {
323+
iov_base: dst.as_ptr() as *mut _,
324+
iov_len: BYTES0.len(),
325+
},
326+
libc::iovec {
327+
iov_base: unsafe { dst.as_ptr().add(BYTES0.len()) } as *mut _,
328+
iov_len: BYTES1.len(),
329+
},
330+
];
331+
unsafe {
332+
ring.submission().push(
333+
&opcode::ReadvFixed::new(
334+
types::Fd(rx.as_raw_fd()),
335+
dst_parts.as_ptr().cast(),
336+
dst_parts.len() as u32,
337+
1,
338+
)
339+
.build()
340+
.user_data(0x666)
341+
.into(),
342+
)?;
343+
}
344+
ring.submit_and_wait(1)?;
345+
for cqe in ring.completion().map(Into::<cqueue::Entry>::into) {
346+
assert_eq!(cqe.user_data_u64(), 0x666);
347+
let len = cqe.result()?;
348+
assert_eq!(len, src.len() as _);
349+
}
350+
351+
ring.submitter().unregister_buffers()?;
352+
353+
assert_eq!(src, dst);
354+
355+
Ok(())
356+
}
357+
252358
pub fn test_file_fsync<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
253359
ring: &mut IoUring<S, C>,
254360
test: &Test,

src/opcode.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,3 +2296,65 @@ opcode! {
22962296
Entry(sqe)
22972297
}
22982298
}
2299+
2300+
opcode! {
2301+
/// Vectored read into a fixed buffer, equivalent to `preadv2(2)`.
2302+
pub struct ReadvFixed {
2303+
fd: { impl sealed::UseFixed },
2304+
iovec: { *const types::iovec },
2305+
len: { u32 },
2306+
buf_index: { u16 },
2307+
;;
2308+
ioprio: u16 = 0,
2309+
offset: u64 = 0,
2310+
rw_flags: types::RwFlags = types::RwFlags::empty(),
2311+
}
2312+
2313+
pub const CODE = sys::IoringOp::ReadvFixed;
2314+
2315+
pub fn build(self) -> Entry {
2316+
let Self { fd, iovec, len, buf_index, offset, ioprio, rw_flags } = self;
2317+
2318+
let mut sqe = sqe_zeroed();
2319+
sqe.opcode = Self::CODE;
2320+
assign_fd!(sqe.fd = fd);
2321+
sqe.off_or_addr2.off = offset as _;
2322+
sqe.addr_or_splice_off_in.addr.ptr = iovec as _;
2323+
sqe.len.len = len;
2324+
sqe.buf.buf_index = buf_index;
2325+
sqe.ioprio.ioprio = ioprio;
2326+
sqe.op_flags.rw_flags = rw_flags;
2327+
Entry(sqe)
2328+
}
2329+
}
2330+
2331+
opcode! {
2332+
/// Vectored write from a fixed buffer, equivalent to `pwritev2(2)`.
2333+
pub struct WritevFixed {
2334+
fd: { impl sealed::UseFixed },
2335+
iovec: { *const sys::iovec },
2336+
len: { u32 },
2337+
buf_index: { u16 },
2338+
;;
2339+
ioprio: u16 = 0,
2340+
offset: u64 = 0,
2341+
rw_flags: types::RwFlags = types::RwFlags::empty()
2342+
}
2343+
2344+
pub const CODE = sys::IoringOp::WritevFixed;
2345+
2346+
pub fn build(self) -> Entry {
2347+
let Self { fd, iovec, len, buf_index, offset, ioprio, rw_flags } = self;
2348+
2349+
let mut sqe = sqe_zeroed();
2350+
sqe.opcode = Self::CODE;
2351+
assign_fd!(sqe.fd = fd);
2352+
sqe.off_or_addr2.off = offset as _;
2353+
sqe.addr_or_splice_off_in.addr.ptr = iovec as _;
2354+
sqe.len.len = len;
2355+
sqe.buf.buf_index = buf_index;
2356+
sqe.ioprio.ioprio = ioprio;
2357+
sqe.op_flags.rw_flags = rw_flags;
2358+
Entry(sqe)
2359+
}
2360+
}

0 commit comments

Comments
 (0)