Skip to content

Commit fb85b91

Browse files
committed
Add ops {ReadvFixed, WritevFixed}
1 parent 77f4ba4 commit fb85b91

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};
@@ -259,6 +260,111 @@ pub fn test_file_writev_readv<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
259260
Ok(())
260261
}
261262

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

src/opcode.rs

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

0 commit comments

Comments
 (0)