1
+ use std:: ptr;
2
+
1
3
use libc:: c_void;
2
4
use rustix:: fd:: { AsFd , AsRawFd , BorrowedFd } ;
3
- use rustix:: io:: Result ;
5
+ use rustix:: io:: { Errno , Result } ;
4
6
use 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 ,
7
10
} ;
11
+ use rustix:: mm:: { MapFlags , ProtFlags } ;
8
12
9
13
fn do_register < FD > (
10
14
fd : FD ,
87
91
Ok ( ( ) )
88
92
}
89
93
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
+
90
107
#[ test]
91
108
fn test_io_uring_register_with ( ) {
92
109
let mut params = io_uring_params:: default ( ) ;
@@ -104,3 +121,53 @@ fn test_io_uring_register_with() {
104
121
unregister_ring ( ring_fd) . unwrap ( ) ;
105
122
register_result. unwrap ( ) ;
106
123
}
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