1+ use std:: ptr;
2+
13use libc:: c_void;
24use rustix:: fd:: { AsFd , AsRawFd , BorrowedFd } ;
3- use rustix:: io:: Result ;
5+ use rustix:: io:: { Errno , Result } ;
46use rustix:: io_uring:: {
5- io_uring_params, io_uring_register_with, io_uring_rsrc_update, io_uring_setup,
6- IoringFeatureFlags , IoringRegisterFlags , IoringRegisterOp ,
7+ io_uring_buf, io_uring_buf_reg, io_uring_buf_ring, io_uring_params, io_uring_register_with,
8+ io_uring_rsrc_update, io_uring_setup, IoringFeatureFlags , IoringRegisterFlags ,
9+ IoringRegisterOp ,
710} ;
11+ use rustix:: mm:: { MapFlags , ProtFlags } ;
812
913fn do_register < FD > (
1014 fd : FD ,
8791 Ok ( ( ) )
8892}
8993
94+ fn register_buf_ring < FD > ( fd : FD , reg : & io_uring_buf_reg ) -> Result < ( ) >
95+ where
96+ FD : AsFd ,
97+ {
98+ do_register (
99+ fd,
100+ false ,
101+ IoringRegisterOp :: RegisterPbufRing ,
102+ reg as * const io_uring_buf_reg as * const c_void ,
103+ 1 ,
104+ )
105+ }
106+
90107#[ test]
91108fn test_io_uring_register_with ( ) {
92109 let mut params = io_uring_params:: default ( ) ;
@@ -104,3 +121,53 @@ fn test_io_uring_register_with() {
104121 unregister_ring ( ring_fd) . unwrap ( ) ;
105122 register_result. unwrap ( ) ;
106123}
124+
125+ #[ test]
126+ fn io_uring_buf_ring_can_be_registered ( ) {
127+ const ENTRIES : usize = 8 ;
128+ const BGID : u16 = 42 ;
129+
130+ let mut params = io_uring_params:: default ( ) ;
131+ let ring_fd = io_uring_setup ( 4 , & mut params) . unwrap ( ) ;
132+
133+ // Test that the kernel version supports IORING_REGISTER_PBUF_RING. If it doesn't, the kernel
134+ // will return EINVAL. Not setting a `ring_addr` on `io_uring_buf_reg` will return `EFAULT`.
135+ if let Err ( e) = register_buf_ring ( ring_fd. as_fd ( ) , & io_uring_buf_reg:: default ( ) ) {
136+ if e == Errno :: INVAL {
137+ // Skip the test, as the current kernel version doesn't support what we need to test.
138+ return ;
139+ }
140+ }
141+
142+ let buf_ring_size = ENTRIES * std:: mem:: size_of :: < io_uring_buf > ( ) ;
143+
144+ let br_ptr = unsafe {
145+ rustix:: mm:: mmap_anonymous (
146+ ptr:: null_mut ( ) ,
147+ buf_ring_size,
148+ ProtFlags :: READ | ProtFlags :: WRITE ,
149+ MapFlags :: PRIVATE ,
150+ )
151+ }
152+ . unwrap ( ) as * mut io_uring_buf_ring ;
153+
154+ let br = unsafe { br_ptr. as_mut ( ) } . expect ( "A valid io_uring_buf_ring struct" ) ;
155+
156+ let reg = io_uring_buf_reg {
157+ ring_addr : br_ptr as u64 ,
158+ ring_entries : ENTRIES as u32 ,
159+ bgid : BGID ,
160+ pad : 0 ,
161+ resv : [ 0u64 ; 3 ] ,
162+ } ;
163+
164+ assert_eq ! ( register_buf_ring( ring_fd, & reg) , Ok ( ( ) ) ) ;
165+
166+ let tail = unsafe { br. tail_or_bufs . tail . as_mut ( ) } ;
167+ tail. tail = 0 ;
168+ let bufs = unsafe { br. tail_or_bufs . bufs . as_mut ( ) . bufs . as_mut_slice ( ENTRIES ) } ;
169+
170+ assert_eq ! ( bufs[ 0 ] . bid, 0 ) ;
171+ bufs[ 7 ] . bid = 7 ;
172+ assert_eq ! ( bufs[ 7 ] . bid, 7 ) ;
173+ }
0 commit comments