1 /**
2  * D header file for the io_uring interface.
3  * Available since Linux 5.1
4  *
5  * Copyright: Copyright Jens Axboe 2019,
6  *            Copyright Christoph Hellwig 2019.
7  * License : $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Authors : Luís Ferreira
9  */
10 module core.sys.linux.io_uring;
11 
12 version (linux):
13 
14 import core.sys.linux.fs : __kernel_rwf_t;
15 
16 extern (C):
17 @nogc:
18 nothrow:
19 
20 /**
21  * IO submission data structure (Submission Queue Entry)
22  */
23 struct io_uring_sqe
24 {
25     /// type of operation for this sqe
26     ubyte opcode;
27     /// IOSQE_* flags
28     ubyte flags;
29     /// ioprio for the request
30     ushort ioprio;
31     /// file descriptor to do IO on
32     int fd;
33     union
34     {
35         /// offset into file
36         ulong off;
37         ulong addr2;
38     }
39 
40     union
41     {
42         /// pointer to buffer or iovecs
43         ulong addr;
44         ulong splice_off_in;
45     }
46 
47     /// buffer size or number of iovecs
48     uint len;
49     union
50     {
51         __kernel_rwf_t rw_flags;
52         uint fsync_flags;
53 
54         /// compatibility
55         ushort poll_events;
56         /// word-reversed for BE
57         uint poll32_events;
58 
59         uint sync_range_flags;
60         uint msg_flags;
61         uint timeout_flags;
62         uint accept_flags;
63         uint cancel_flags;
64         uint open_flags;
65         uint statx_flags;
66         uint fadvise_advice;
67         uint splice_flags;
68         uint rename_flags;
69         uint unlink_flags;
70     }
71 
72     /// data to be passed back at completion time
73     ulong user_data;
74     union
75     {
76         struct
77         {
78             /**
79              * pack this to avoid bogus arm OABI complaints
80              */
81             union
82             {
83                 align (1):
84 
85                 /// index into fixed buffers, if used
86                 ushort buf_index;
87                 /// for grouped buffer selection
88                 ushort buf_group;
89             }
90 
91             /// personality to use, if used
92             ushort personality;
93             int splice_fd_in;
94         }
95 
96         ulong[3] __pad2;
97     }
98 }
99 
100 enum
101 {
102     IOSQE_FIXED_FILE_BIT = 0,
103     IOSQE_IO_DRAIN_BIT = 1,
104     IOSQE_IO_LINK_BIT = 2,
105     IOSQE_IO_HARDLINK_BIT = 3,
106     IOSQE_ASYNC_BIT = 4,
107     IOSQE_BUFFER_SELECT_BIT = 5
108 }
109 
110 enum
111 {
112     /// use fixed fileset
113     IOSQE_FIXED_FILE = 1U << IOSQE_FIXED_FILE_BIT,
114     /// issue after inflight IO
115     IOSQE_IO_DRAIN = 1U << IOSQE_IO_DRAIN_BIT,
116     /// links next sqe
117     IOSQE_IO_LINK = 1U << IOSQE_IO_LINK_BIT,
118     /// like LINK, but stronger
119     IOSQE_IO_HARDLINK = 1U << IOSQE_IO_HARDLINK_BIT,
120     /// always go async
121     IOSQE_ASYNC = 1U << IOSQE_ASYNC_BIT,
122     /// select buffer from sqe.buf_group
123     IOSQE_BUFFER_SELECT = 1U << IOSQE_BUFFER_SELECT_BIT,
124 }
125 
126 /**
127  * io_uring_setup() flags
128  */
129 enum
130 {
131     /// io_context is polled
132     IORING_SETUP_IOPOLL = 1U << 0,
133     /// SQ poll thread
134     IORING_SETUP_SQPOLL = 1U << 1,
135     /// sq_thread_cpu is valid
136     IORING_SETUP_SQ_AFF = 1U << 2,
137     /// app defines CQ size
138     IORING_SETUP_CQSIZE = 1U << 3,
139     /// clamp SQ/CQ ring sizes
140     IORING_SETUP_CLAMP = 1U << 4,
141     /// attach to existing wq
142     IORING_SETUP_ATTACH_WQ = 1U << 5,
143     /// start with ring disabled
144     IORING_SETUP_R_DISABLED = 1U << 6,
145 }
146 
147 enum
148 {
149     IORING_OP_NOP = 0,
150     IORING_OP_READV = 1,
151     IORING_OP_WRITEV = 2,
152     IORING_OP_FSYNC = 3,
153     IORING_OP_READ_FIXED = 4,
154     IORING_OP_WRITE_FIXED = 5,
155     IORING_OP_POLL_ADD = 6,
156     IORING_OP_POLL_REMOVE = 7,
157     IORING_OP_SYNC_FILE_RANGE = 8,
158     IORING_OP_SENDMSG = 9,
159     IORING_OP_RECVMSG = 10,
160     IORING_OP_TIMEOUT = 11,
161     IORING_OP_TIMEOUT_REMOVE = 12,
162     IORING_OP_ACCEPT = 13,
163     IORING_OP_ASYNC_CANCEL = 14,
164     IORING_OP_LINK_TIMEOUT = 15,
165     IORING_OP_CONNECT = 16,
166     IORING_OP_FALLOCATE = 17,
167     IORING_OP_OPENAT = 18,
168     IORING_OP_CLOSE = 19,
169     IORING_OP_FILES_UPDATE = 20,
170     IORING_OP_STATX = 21,
171     IORING_OP_READ = 22,
172     IORING_OP_WRITE = 23,
173     IORING_OP_FADVISE = 24,
174     IORING_OP_MADVISE = 25,
175     IORING_OP_SEND = 26,
176     IORING_OP_RECV = 27,
177     IORING_OP_OPENAT2 = 28,
178     IORING_OP_EPOLL_CTL = 29,
179     IORING_OP_SPLICE = 30,
180     IORING_OP_PROVIDE_BUFFERS = 31,
181     IORING_OP_REMOVE_BUFFERS = 32,
182     IORING_OP_TEE = 33,
183     IORING_OP_SHUTDOWN = 34,
184     IORING_OP_RENAMEAT = 35,
185     IORING_OP_UNLINKAT = 36,
186 
187     IORING_OP_LAST = 37
188 }
189 
190 enum
191 {
192     IORING_FSYNC_DATASYNC = 1U << 0,
193 }
194 
195 enum
196 {
197     IORING_TIMEOUT_ABS = 1U << 0,
198     IORING_TIMEOUT_UPDATE = 1U << 1,
199 }
200 
201 enum SPLICE_F_FD_IN_FIXED = 1U << 31;
202 
203 /**
204  * IO completion data structure (Completion Queue Entry)
205  */
206 struct io_uring_cqe
207 {
208     /// submission passed back
209     ulong user_data;
210     /// result code for this event
211     int res;
212 
213     uint flags;
214 }
215 
216 /**
217  * If set, the upper 16 bits are the buffer ID
218  */
219 enum IORING_CQE_F_BUFFER = 1U << 0;
220 
221 enum
222 {
223     IORING_CQE_BUFFER_SHIFT = 16,
224 }
225 
226 /**
227  * Magic offsets for the application to mmap the data it needs
228  */
229 enum
230 {
231     IORING_OFF_SQ_RING = 0UL,
232     IORING_OFF_CQ_RING = 0x8000000UL,
233     IORING_OFF_SQES = 0x10000000UL,
234 }
235 
236 /**
237  * Filled with the offset for mmap(2)
238  */
239 struct io_sqring_offsets
240 {
241     uint head;
242     uint tail;
243     uint ring_mask;
244     uint ring_entries;
245     uint flags;
246     uint dropped;
247     uint array;
248     uint resv1;
249     ulong resv2;
250 }
251 
252 enum
253 {
254     /// needs io_uring_enter wakeup
255     IORING_SQ_NEED_WAKEUP = 1U << 0,
256     /// CQ ring is overflown
257     IORING_SQ_CQ_OVERFLOW = 1U << 1,
258 }
259 
260 struct io_cqring_offsets
261 {
262     uint head;
263     uint tail;
264     uint ring_mask;
265     uint ring_entries;
266     uint overflow;
267     uint cqes;
268     uint flags;
269     uint resv1;
270     ulong resv2;
271 }
272 
273 enum
274 {
275     /// disable eventfd notifications
276     IORING_CQ_EVENTFD_DISABLED = 1U << 0,
277 }
278 
279 /**
280  * io_uring_enter(2) flags
281  */
282 enum
283 {
284     IORING_ENTER_GETEVENTS = 1U << 0,
285     IORING_ENTER_SQ_WAKEUP = 1U << 1,
286     IORING_ENTER_SQ_WAIT = 1U << 2,
287     IORING_ENTER_EXT_ARG = 1U << 3,
288 }
289 
290 /**
291  * Passed in for io_uring_setup(2)
292  */
293 struct io_uring_params
294 {
295     uint sq_entries;
296     uint cq_entries;
297     uint flags;
298     uint sq_thread_cpu;
299     uint sq_thread_idle;
300     uint features;
301     uint wq_fd;
302     uint[3] resv;
303     io_sqring_offsets sq_off;
304     io_cqring_offsets cq_off;
305 }
306 
307 enum
308 {
309     IORING_FEAT_SINGLE_MMAP = 1U << 0,
310     IORING_FEAT_NODROP = 1U << 1,
311     IORING_FEAT_SUBMIT_STABLE = 1U << 2,
312     IORING_FEAT_RW_CUR_POS = 1U << 3,
313     IORING_FEAT_CUR_PERSONALITY = 1U << 4,
314     IORING_FEAT_FAST_POLL = 1U << 5,
315     IORING_FEAT_POLL_32BITS = 1U << 6,
316     IORING_FEAT_SQPOLL_NONFIXED = 1U << 7,
317     IORING_FEAT_EXT_ARG = 1U << 8,
318 }
319 
320 /**
321  * io_uring_register(2) opcodes and arguments
322  */
323 enum
324 {
325     IORING_REGISTER_BUFFERS = 0,
326     IORING_UNREGISTER_BUFFERS = 1,
327     IORING_REGISTER_FILES = 2,
328     IORING_UNREGISTER_FILES = 3,
329     IORING_REGISTER_EVENTFD = 4,
330     IORING_UNREGISTER_EVENTFD = 5,
331     IORING_REGISTER_FILES_UPDATE = 6,
332     IORING_REGISTER_EVENTFD_ASYNC = 7,
333     IORING_REGISTER_PROBE = 8,
334     IORING_REGISTER_PERSONALITY = 9,
335     IORING_UNREGISTER_PERSONALITY = 10,
336     IORING_REGISTER_RESTRICTIONS = 11,
337     IORING_REGISTER_ENABLE_RINGS = 12,
338 
339     IORING_REGISTER_LAST = 13
340 }
341 
342 struct io_uring_files_update
343 {
344     uint offset;
345     uint resv;
346     ulong fds;
347 }
348 
349 enum IO_URING_OP_SUPPORTED = 1U << 0;
350 
351 struct io_uring_probe_op
352 {
353     ubyte op;
354     ubyte resv;
355 
356     /// IO_URING_OP_* flags
357     ushort flags;
358     uint resv2;
359 }
360 
361 struct io_uring_probe
362 {
363     /// last opcode supported
364     ubyte last_op;
365 
366     /// length of ops[] array below
367     ubyte ops_len;
368 
369     ushort resv;
370     uint[3] resv2;
371     io_uring_probe_op[0] ops;
372 }
373 
374 struct io_uring_restriction
375 {
376     ushort opcode;
377 
378     union
379     {
380         ubyte register_op;
381         ubyte sqe_op;
382         ubyte sqe_flags;
383     }
384 
385     ubyte resv;
386     uint[3] resv2;
387 }
388 
389 enum
390 {
391     /// Allow an io_uring_register(2) opcode
392     IORING_RESTRICTION_REGISTER_OP = 0,
393 
394     /// Allow an sqe opcode
395     IORING_RESTRICTION_SQE_OP = 1,
396 
397     /// Allow sqe flags
398     IORING_RESTRICTION_SQE_FLAGS_ALLOWED = 2,
399 
400     /// Require sqe flags (these flags must be set on each submission)
401     IORING_RESTRICTION_SQE_FLAGS_REQUIRED = 3,
402 
403     IORING_RESTRICTION_LAST = 4
404 }
405 
406 struct io_uring_getevents_arg
407 {
408     ulong sigmask;
409     uint sigmask_sz;
410     uint pad;
411     ulong ts;
412 }