Skip to content

Commit b175a22

Browse files
authored
Update for recent kernels (up to 6.10) (#296)
* Updated for new capabilities in kernels 6.8, 6.9, 6.10 including FixedFdInstall, FTruncate operations as well as bundled recv and send. Added test for bundled send and recv feature flag (available from kernel 6.10). Implemented tests accordingly. * Fixed formatting * Updated comment spelling. Renamed FTruncate to Ftruncate for consistency. * Changed sys::IOSQE_FIXED_FILE_BIT with Flags::FIXED_FILE.bits as requested * Replaced sys::IOSQE_BUFFER_SELECT_BIT with BUFFER_SELECT.bits as requested
1 parent c1c3773 commit b175a22

File tree

6 files changed

+608
-18
lines changed

6 files changed

+608
-18
lines changed

io-uring-test/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ fn test<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
103103
#[cfg(not(feature = "ci"))]
104104
tests::fs::test_statx(&mut ring, &test)?;
105105
tests::fs::test_file_splice(&mut ring, &test)?;
106+
tests::fs::test_ftruncate(&mut ring, &test)?;
107+
tests::fs::test_fixed_fd_install(&mut ring, &test)?;
106108

107109
// timeout
108110
tests::timeout::test_timeout(&mut ring, &test)?;
@@ -117,6 +119,7 @@ fn test<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
117119
tests::net::test_tcp_write_read(&mut ring, &test)?;
118120
tests::net::test_tcp_writev_readv(&mut ring, &test)?;
119121
tests::net::test_tcp_send_recv(&mut ring, &test)?;
122+
tests::net::test_tcp_send_bundle(&mut ring, &test)?;
120123
tests::net::test_tcp_zero_copy_send_recv(&mut ring, &test)?;
121124
tests::net::test_tcp_zero_copy_send_fixed(&mut ring, &test)?;
122125
tests::net::test_tcp_sendmsg_recvmsg(&mut ring, &test)?;
@@ -130,6 +133,9 @@ fn test<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
130133
tests::net::test_tcp_buffer_select_recvmsg(&mut ring, &test)?;
131134
tests::net::test_tcp_buffer_select_readv(&mut ring, &test)?;
132135
tests::net::test_tcp_recv_multi(&mut ring, &test)?;
136+
tests::net::test_tcp_recv_bundle(&mut ring, &test)?;
137+
tests::net::test_tcp_recv_multi_bundle(&mut ring, &test)?;
138+
133139
tests::net::test_tcp_shutdown(&mut ring, &test)?;
134140
tests::net::test_socket(&mut ring, &test)?;
135141
tests::net::test_udp_recvmsg_multishot(&mut ring, &test)?;

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

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::Test;
33
use io_uring::{cqueue, opcode, squeue, types, IoUring};
44
use std::ffi::CString;
55
use std::fs;
6-
use std::io::Write;
6+
use std::io::{Read, Write};
77
use std::os::unix::ffi::OsStrExt;
88
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
99

@@ -810,3 +810,130 @@ pub fn test_file_splice<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
810810

811811
Ok(())
812812
}
813+
814+
pub fn test_ftruncate<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
815+
ring: &mut IoUring<S, C>,
816+
test: &Test,
817+
) -> anyhow::Result<()> {
818+
require!(
819+
test;
820+
test.probe.is_supported(opcode::Ftruncate::CODE);
821+
);
822+
823+
println!("test ftruncate");
824+
825+
let dir = tempfile::TempDir::new_in(".")?;
826+
let dir = dir.path();
827+
let file = dir.join("io-uring-test-file-input");
828+
829+
let input = &[0x9f; 1024];
830+
831+
fs::write(&file, input)?;
832+
let fd = fs::OpenOptions::new().write(true).open(&file)?;
833+
let fd = types::Fd(fd.as_raw_fd());
834+
let ftruncate_e = opcode::Ftruncate::new(fd, 512);
835+
836+
unsafe {
837+
ring.submission()
838+
.push(&ftruncate_e.build().user_data(0x33).into())
839+
.expect("queue is full");
840+
}
841+
842+
ring.submit_and_wait(1)?;
843+
844+
let cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
845+
846+
assert_eq!(cqes.len(), 1);
847+
assert_eq!(cqes[0].user_data(), 0x33);
848+
assert_eq!(cqes[0].result(), 0);
849+
assert_eq!(
850+
fs::read(&file).expect("could not read truncated file"),
851+
&input[..512]
852+
);
853+
854+
let ftruncate_e = opcode::Ftruncate::new(fd, 0);
855+
856+
unsafe {
857+
ring.submission()
858+
.push(&ftruncate_e.build().user_data(0x34).into())
859+
.expect("queue is full");
860+
}
861+
862+
ring.submit_and_wait(1)?;
863+
864+
let cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
865+
866+
assert_eq!(cqes.len(), 1);
867+
assert_eq!(cqes[0].user_data(), 0x34);
868+
assert_eq!(cqes[0].result(), 0);
869+
assert_eq!(
870+
fs::metadata(&file)
871+
.expect("could not read truncated file")
872+
.len(),
873+
0
874+
);
875+
876+
Ok(())
877+
}
878+
879+
pub fn test_fixed_fd_install<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
880+
ring: &mut IoUring<S, C>,
881+
test: &Test,
882+
) -> anyhow::Result<()> {
883+
require!(
884+
test;
885+
test.probe.is_supported(opcode::Read::CODE);
886+
test.probe.is_supported(opcode::FixedFdInstall::CODE);
887+
);
888+
889+
println!("test fixed_fd_install");
890+
891+
let dir = tempfile::TempDir::new_in(".")?;
892+
let dir = dir.path();
893+
let file = dir.join("io-uring-test-file-input");
894+
895+
let input = &[0x9f; 1024];
896+
let mut output = vec![0; 1024];
897+
898+
fs::write(&file, input)?;
899+
let fd = fs::OpenOptions::new().read(true).open(&file)?;
900+
let fd = types::Fd(fd.as_raw_fd());
901+
ring.submitter().register_files(&[fd.0])?;
902+
let fd = types::Fixed(0);
903+
904+
let read_e = opcode::Read::new(fd, output.as_mut_ptr(), output.len() as _);
905+
unsafe {
906+
ring.submission()
907+
.push(&read_e.build().user_data(0x01).into())
908+
.expect("queue is full");
909+
}
910+
911+
assert_eq!(ring.submit_and_wait(1)?, 1);
912+
let cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
913+
assert_eq!(cqes.len(), 1);
914+
assert_eq!(cqes[0].user_data(), 0x01);
915+
assert_eq!(cqes[0].result(), 1024);
916+
assert_eq!(output, input);
917+
918+
let fixed_fd_install_e = opcode::FixedFdInstall::new(fd, 0);
919+
920+
unsafe {
921+
ring.submission()
922+
.push(&fixed_fd_install_e.build().user_data(0x02).into())
923+
.expect("queue is full");
924+
}
925+
926+
ring.submit_and_wait(1)?;
927+
928+
let cqes: Vec<cqueue::Entry> = ring.completion().map(Into::into).collect();
929+
930+
assert_eq!(cqes.len(), 1);
931+
assert_eq!(cqes[0].user_data(), 0x02);
932+
let fd = cqes[0].result();
933+
assert!(fd > 0);
934+
let mut file = unsafe { fs::File::from_raw_fd(fd) };
935+
file.read_exact(&mut output)?;
936+
assert_eq!(output, input);
937+
938+
Ok(())
939+
}

0 commit comments

Comments
 (0)