File: io_uring_registered_files.7

package info (click to toggle)
liburing 2.14-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,448 kB
  • sloc: ansic: 59,512; sh: 816; makefile: 603; cpp: 32
file content (228 lines) | stat: -rw-r--r-- 7,158 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
.\" SPDX-License-Identifier: LGPL-2.0-or-later
.\"
.TH io_uring_registered_files 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
.SH NAME
io_uring_registered_files \- io_uring registered files overview
.SH DESCRIPTION
Registered files (also known as fixed files) are a performance
optimization feature of
.B io_uring
that allows applications to pre-register a set of file descriptors with
the kernel. When files are registered, the kernel takes a reference to
each file, avoiding the overhead of looking up file descriptors and
taking references for each I/O operation.
.SS Why use registered files?
For every I/O operation that uses a file descriptor, the kernel must:
.IP \(bu 2
Look up the file descriptor in the process's file descriptor table
.IP \(bu
Take a reference to the file to ensure it remains valid during the
operation
.IP \(bu
Release the reference when the operation completes
.PP
For applications performing many I/O operations, especially on threaded
applications where the file table is shared (making reference counting
more expensive), these overheads accumulate. By registering files once,
the reference is held for the lifetime of the registration, and
operations can use the file directly without per-operation lookups or
reference counting.

Registered files are most beneficial for applications that:
.IP \(bu 2
Perform many I/O operations on the same set of files
.IP \(bu
Are multi-threaded (where file table operations are more expensive)
.IP \(bu
Need the lowest possible per-I/O overhead
.SS Registering files
Files are registered using
.BR io_uring_register_files (3)
or
.BR io_uring_register_files_tags (3).
The files are described using an array of file descriptors:
.PP
.in +4n
.EX
int fds[3];
fds[0] = open("file1", O_RDONLY);
fds[1] = open("file2", O_RDONLY);
fds[2] = open("file3", O_WRONLY | O_CREAT, 0644);

ret = io_uring_register_files(ring, fds, 3);
.EE
.in
.PP
Once registered, the original file descriptors can be closed if desired.
The kernel holds its own references to the underlying files.
.SS Using registered files
To use a registered file in an I/O operation, set the
.B IOSQE_FIXED_FILE
flag in the SQE's
.I flags
field, and use the index into the registered file array (not the original
file descriptor) in the
.I fd
field:
.PP
.in +4n
.EX
struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
io_uring_prep_read(sqe, 0, buf, len, offset);  /* index 0, not fd */
io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
.EE
.in
.PP
The index is 0-based into the array passed to
.BR io_uring_register_files (3).
.SS Sparse file registration
The file array can be sparse, meaning some slots can be empty. Empty
slots are indicated by setting the file descriptor to \-1. Applications
can create a fully sparse table using
.BR io_uring_register_files_sparse (3)
and fill in slots later:
.PP
.in +4n
.EX
/* Create sparse table with 100 slots */
ret = io_uring_register_files_sparse(ring, 100);

/* Later, fill in slot 5 */
int fd = open("file", O_RDONLY);
ret = io_uring_register_files_update(ring, 5, &fd, 1);
.EE
.in
.SS Updating registered files
Registered files can be updated using
.BR io_uring_register_files_update (3)
or
.BR io_uring_register_files_update_tag (3).
This can:
.IP \(bu 2
Replace an existing file with a new one
.IP \(bu
Fill in an empty slot
.IP \(bu
Remove a file by setting the descriptor to \-1
.PP
To skip updating certain slots while updating others, use the special
value
.BR IORING_REGISTER_FILES_SKIP .
.PP
.in +4n
.EX
int fds[3];
fds[0] = new_fd;                        /* replace slot 0 */
fds[1] = IORING_REGISTER_FILES_SKIP;    /* leave slot 1 unchanged */
fds[2] = -1;                            /* remove slot 2 */

ret = io_uring_register_files_update(ring, 0, fds, 3);
.EE
.in
.PP
Updates do not require the ring to be idle on kernels 5.13 and later.
On older kernels, updates would wait for in-flight operations to complete.
.SS File tagging
When using
.BR io_uring_register_files_tags (3)
or
.BR io_uring_register_files_update_tag (3),
each file can be associated with a tag value. When a file is unregistered
(either explicitly or by replacement), and there are no more in-flight
operations using that file, a completion queue entry is posted with
.I user_data
set to the tag value and all other fields zeroed.

This notification mechanism allows applications to know when it is safe
to perform cleanup actions associated with the file.
.SS Direct file descriptors
Some io_uring operations can allocate file descriptors directly into the
registered file table, avoiding the regular file descriptor table
entirely. This is done by setting the
.I file_index
field in the SQE (using
.BR io_uring_sqe_set_target_fixed_file (3))
to the desired slot, or using
.B IORING_FILE_INDEX_ALLOC
to have io_uring allocate the next available slot.

Operations that support direct descriptors include:
.IP \(bu 2
.B IORING_OP_OPENAT
/
.B IORING_OP_OPENAT2
.IP \(bu
.B IORING_OP_ACCEPT
.IP \(bu
.B IORING_OP_SOCKET
.IP \(bu
.B IORING_OP_PIPE
.PP
When using
.BR IORING_FILE_INDEX_ALLOC ,
the application should use
.BR io_uring_register_file_alloc_range (3)
to specify which range of the file table should be used for allocations.
.PP
.in +4n
.EX
/* Reserve slots 50-99 for dynamic allocation */
io_uring_register_file_alloc_range(ring, 50, 50);

/* Accept with direct descriptor allocation */
struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
io_uring_prep_accept_direct(sqe, listen_fd, NULL, NULL, 0,
                            IORING_FILE_INDEX_ALLOC);
.EE
.in
.PP
The allocated slot index is returned in the CQE
.I res
field on success.
.SS Closing direct descriptors
Direct descriptors (files that exist only in the registered file table)
can be closed using
.B IORING_OP_CLOSE
with the
.B IOSQE_FIXED_FILE
flag set, or by updating the slot to \-1 using
.BR io_uring_register_files_update (3).
.SS Unregistering files
Files are unregistered using
.BR io_uring_unregister_files (3).
This releases all registered files. Files are also automatically
unregistered when the io_uring instance is destroyed.

Applications do not need to explicitly unregister files before shutting
down the ring.
.SH NOTES
.IP \(bu 2
Registered files provide the most benefit for applications performing
many operations on the same files, especially multi-threaded applications.
.IP \(bu
Direct descriptors (files that only exist in the registered table) are
not visible to operations outside io_uring, such as
.BR read (2)
or
.BR write (2).
.IP \(bu
The
.B IOSQE_FIXED_FILE
flag must be set when using a registered file index; without it, the
.I fd
field is interpreted as a regular file descriptor.
.IP \(bu
It is an error to use
.B IOSQE_FIXED_FILE
with an index that does not correspond to a registered file.
.SH SEE ALSO
.BR io_uring (7),
.BR io_uring_registered_buffers (7),
.BR io_uring_register_files (3),
.BR io_uring_register_files_tags (3),
.BR io_uring_register_files_sparse (3),
.BR io_uring_register_files_update (3),
.BR io_uring_register_files_update_tag (3),
.BR io_uring_unregister_files (3),
.BR io_uring_register_file_alloc_range (3)