Skip to content

Commit e839343

Browse files
committed
Add ops {ReadvFixed, WritevFixed}
1 parent 05ca293 commit e839343

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-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: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,113 @@ pub fn test_file_writev_readv<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
263263
Ok(())
264264
}
265265

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