Completion¶
Introduction¶
These functions deal with completion of I/O requests in io_uring
. The snippet below is from the example cat with liburing. While there are other possible ways, it shows a general way in which you can use completion related functions. Once a request or multiple requests have been submitted, you can wait for a completion and process it as shown below.
int get_completion_and_print(struct io_uring *ring) {
struct io_uring_cqe *cqe;
int ret = io_uring_wait_cqe(ring, &cqe);
if (ret < 0) {
perror("io_uring_wait_cqe");
return 1;
}
if (cqe->res < 0) {
/* The system call invoked asynchonously failed */
return 1;
}
/* Retrieve user data from CQE */
struct file_info *fi = io_uring_cqe_get_data(cqe);
/* process this request here */
/* Mark this completion as seen */
io_uring_cqe_seen(ring, cqe);
return 0;
}
You can wait for a completion by calling
io_uring_wait_cqe()
. This function blocks until at least one completion is available.It fills up details of the completion in the
io_uring_cqe
structure.This structure’s
res
member contains the return value of the system call that was executed as part of the request. For example, ifio_uring_prep_read()
was called to process a read(2) like request,res
will contain the number of characters read or if it is less than zero, denotes that read(2) faced an error.In
io_uring
, you can set a user data field in the submission side, which with kernel will then make available unchanged on the completion side. You can use this to uniquely identify requests. You can get the user data pointer from the CQE by callingio_uring_cqe_get_data()
.Once you process the information you got from the completion, you need to mark the CQE as “seen”. You can do this with the
io_uring_cqe_seen()
function.
Reference¶
-
int
io_uring_wait_cqe
(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)¶ Returns an I/O completion, waiting for it if necessary.
Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.
Return value
Returns 0 with
cqe_ptr
filled in on success, -errno on failure.
-
int
io_uring_wait_cqe_nr
(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr)¶ Return an IO completion, waiting for
wait_nr
completions if one isn’t readily available.Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.wait_nr: number of completions to wait for.
Return value
Returns 0 with
cqe_ptr
filled in on success,-errno
on failure.
-
int
io_uring_wait_cqes
(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr, struct __kernel_timespec *ts, sigset_t *sigmask)¶ Like
io_uring_wait_cqe()
, except it accepts a timeout value as well. Note that an SQE is used internally to handle the timeout. Applications using this function must never setsqe->user_data
toLIBURING_UDATA_TIMEOUT
.If
ts
is specified, the application need not callio_uring_submit()
before calling this function, as it will be done internally. From this it also follows that this function isn’t safe to use for applications that split SQ and CQ handling between two threads and expect that to work without synchronization, as this function manipulates both the SQ and CQ side.Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.wait_nr: number of completions to wait for.
ts: pointer to a
__kernel_timespec
structure.sigmask: a pointer to
sigset_t
, the set of signals to block. The prevailing signal mask is restored before returning.
Return value
Returns 0 with
cqe_ptr
filled in on success,-errno
on failure.
-
int
io_uring_wait_cqe_timeout
(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, struct __kernel_timespec *ts)¶ Same as the
io_uring_wait_cqes()
except it does not take asigmask
argument and always setswait_nr
to 1.
-
int
io_uring_peek_cqe
(struct io_uring *ring, struct io_uring_cqe **cqe_ptr)¶ Returns an I/O completion, if one is readily available. Doesn’t wait.
Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.
Return value
Returns 0 with cqe_ptr filled in on success, -errno on failure.
-
unsigned
io_uring_peek_batch_cqe
(struct io_uring *ring, struct io_uring_cqe **cqes, unsigned count)¶ Fills in an array of I/O completions up to
count
, if they are available, returning the count of completions filled. Does not wait for completions. They have to be already available for them to be returned by this function.Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.count: count of completions to fetch.
Return value
Returns the count of I/O completions filled.
-
void *
io_uring_cqe_get_data
(const struct io_uring_cqe *cqe)¶ Returns pointer to user data set with :c:func`io_uring_sqe_set_data`.
Parameters
cqe: pointer to the CQE from which to fetch the user data pointer.
Return value
Returns pointer to user data.
-
void
io_uring_cqe_seen
(struct io_uring *ring, struct io_uring_cqe *cqe)¶ Must be called after
io_uring_peek_cqe()
orio_uring_wait_cqe()
and after the cqe has been processed by the application.Parameters
ring:
io_uring
structure as set up byio_uring_queue_init()
.cqe_ptr: pointer to a pointer to a
io_uring_cqe
structure.