Skip to main content

Crate liburing_rs

Crate liburing_rs 

Source
Expand description

Rust bindings for io_uring via a transliteration of Jens Axboe’s liburing.

Crates.io lib.rs Documentation

Building this crate successfully may require the following in your .cargo/config.toml:

[env]
CLANG_PATH = "/usr/bin/clang-20"
LIBCLANG_PATH = "/usr/lib/llvm-20/lib"

in order for bindgen to successfully generate the required struct definitions.


This crate implements an almost pure Rust version of Jens Axboe’s liburing. All the good names were taken so the package’s name is axboe-liburing but the imported crate is liburing_rs.

liburing has tremendous value in that it’s a low-level unopinionated set of helpers that form a complete vocabulary for using io_uring. Originally designed as a set of test helpers, liburing is used to setup and teardown rings, register buffer groups, and create and manage SQEs and CQEs. liburing’s API offers users a comprehensive way of using io_uring in a simple manner.

axboe-liburing implements the entire header liburing.h in native Rust so that everything is as equally inlined as if you were using the library from C or C++. This covers around 142 public functions.

Add the crate with:

cargo add axboe-liburing

axboe-liburing ships with the liburing source and builds liburing.a, statically linking it in via the build.rs. This means that axboe-liburing requires a C toolchain be present on the system in order to build. Typical conventions are followed, the environment variables CC, CXX are used to set the C and C++ compilers.

CC=clang-19 CXX=clang++-19 cargo build

Read the docs for each module in Modules for a high-level overview of io_uring and each feature.

§Building Tests

axboe-liburing includes a few Rust-specific tests to verify the basic flow works but the lion’s share of the testing is in recycling what already exists in liburing proper. To this end, we need objcopy in order to weaken the io_uring_get_sqe() symbol present in liburing.a. When cross-compiling, it can be important to specify the objcopy being used. The objcopy binary can be set via the OBJCOPY environment variable. objcopy ships with gcc toolchains.

Example building liburing tests with liburing-rs:

export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
export OBJCOPY=aarch64-linux-gnu-objcopy
export CARGO_TOOLCHAIN=aarch64-unknown-linux-gnu
make -C test liburing_rs_tests -j$(nproc)

axboe-liburing is also tested using sanitizers as well. To build the tests with sanitization enabled, one needs to enable the sanitizers feature. This causes the crate to build liburing.a with sanitization enabled.

RUSTFLAGS='-Zsanitizer=address' cargo +nightly test --features sanitizers --target x86_64-unknown-linux-gnu -Zbuild-std

For building the liburing_rs_tests target in test/Makefile, one needs to first configure the project to use sanitization.

# for liburing_rs_test.a, needed for the C test files to link against
./configure --enable-sanitizer

# builds everything, including C the default tests which are relied upon to exist by other tests
make all -j$(nproc)

# build a static library that exports everything from the Rust crate and use a shim header in the
# test files so that they link against the Rust-derived staticlib
make -C test liburing_rs_tests -j$(nproc)

§Example

Examples can be found in the main repo: https://github.com/axboe/liburing/tree/master/examples

extern crate liburing_rs;

use std::{mem::zeroed, ptr, time::Duration};

use liburing_rs::*;

pub fn queue_init() {
    // Setup the ring.
    //
    // We create a stack-local instance of `struct io_uring` and use
    // the `io_uring_queue_init` function to initialize all of its
    // fields, using a submission queue size of 64. liburing sets
    // the size of the CQ to twice the SQ size by default.
    //
    let mut ring = unsafe { zeroed::<io_uring>() };
    let ring = &raw mut ring;
    let r = unsafe { io_uring_queue_init(64, ring, 0) };
    assert_eq!(r, 0);

    // Grab a pointer to an unused SQE from the SQ
    let sqe = unsafe { io_uring_get_sqe(ring) };
    assert!(!sqe.is_null());

    // We're going to create an SQE that completes after a specified
    // amount of time, in this case 250ms. We introduce a cast for `ts`
    // because liburing expects a pointer to `__kernel_timespec` which
    // is layout compatible.
    //
    let dur = Duration::from_millis(250);
    let mut ts: timespec = dur.into();
    let ts = (&raw mut ts).cast();

    unsafe { io_uring_prep_timeout(sqe, ts, 0, 0) };
    unsafe { io_uring_sqe_set_data64(sqe, 1234) };

    // Submit the SQ to the kernel for processing. `io_uring_submit` returns
    // the number of submitted entries that are going to be processed. In this case,
    // we only have 1 work item.
    //
    let n = unsafe { io_uring_submit(ring) };
    assert_eq!(n, 1);

    // Grab the first CQE off the queue and make sure it has the same `user_data`
    // field that we originally set.
    //
    let mut cqe = ptr::null_mut::<io_uring_cqe>();
    unsafe { io_uring_wait_cqe(ring, &raw mut cqe) };

    assert!(!cqe.is_null());
    assert_eq!(unsafe { (*cqe).user_data }, 1234);

    // Mark the CQE as seen so that its spot can be reused as more
    // completions arrive.
    //
    unsafe { io_uring_cqe_seen(ring, cqe) };

    // Teardown the ring.
    //
    unsafe { io_uring_queue_exit(ring) };
}

Modules§

io_uring_cancelation
io_uring request cancelation overview
io_uring_linked_requests
io_uring linked requests overview
io_uring_multishot
io_uring multishot requests overview
io_uring_overview
Asynchronous I/O facility
io_uring_provided_buffers
io_uring provided buffer rings overview
io_uring_registered_buffers
io_uring registered buffers overview
io_uring_registered_files
io_uring registered files overview
io_uring_setup_flags
io_uring ring setup flags overview
io_uring_sqpoll
io_uring submission queue polling overview

Structs§

io_uring
io_uring_clone_buffers
Clones registered buffers between rings
io_uring_cq
io_uring_cqe
io_uring_sq
io_uring_sqe

Constants§

IOSQE_ASYNC
IOSQE_BUFFER_SELECT
IOSQE_CQE_SKIP_SUCCESS
IOSQE_FIXED_FILE
IOSQE_IO_DRAIN
IOSQE_IO_HARDLINK
IOSQE_IO_LINK

Functions§

__io_uring_buf_ring_cq_advance⚠
Advance index of provided buffer and CQ ring
__io_uring_clone_buffers⚠
Clones registered buffers between rings
__io_uring_clone_buffers_offset⚠
Clones registered buffers between rings
io_uring_buf_ring_add⚠
Add buffers to a shared buffer ring
io_uring_buf_ring_advance⚠
Advance index of provided buffer in buffer ring
io_uring_buf_ring_available⚠
Return number of unconsumed provided ring buffer entries
io_uring_buf_ring_cq_advance⚠
Advance index of provided buffer and CQ ring
io_uring_buf_ring_init⚠
Initialise a buffer ring
io_uring_buf_ring_mask
Calculate buffer ring mask size
io_uring_check_version⚠
Functions and macros to check the liburing version
io_uring_clone_buffers⚠
Clones registered buffers between rings
io_uring_clone_buffers_offset⚠
Clones registered buffers between rings
io_uring_close_ring_fd⚠
Close a ring file descriptor and use it only via registered index
io_uring_cq_advance⚠
Mark one or more io_uring completion events as consumed
io_uring_cq_eventfd_enabled⚠
Check if eventfd notifications are enabled
io_uring_cq_eventfd_toggle⚠
Toggle eventfd notifications on or off
io_uring_cq_has_overflow⚠
Returns if there are overflow entries waiting to move to the CQ ring
io_uring_cq_ready⚠
Returns number of unconsumed ready entries in the CQ ring
io_uring_cqe_get_data⚠
Get user data for completion event
io_uring_cqe_get_data64⚠
Get user data for completion event
io_uring_cqe_nr⚠
Return the number of CQ ring slots consumed by a CQE
io_uring_cqe_seen⚠
Mark io_uring completion event as consumed
io_uring_enable_rings⚠
Enable a disabled ring
io_uring_enter⚠
Initiate and/or complete asynchronous I/O
io_uring_enter2⚠
Initiate and/or complete asynchronous I/O
io_uring_for_each_cqe⚠
Iterate pending completion events
io_uring_free_buf_ring⚠
Register and free a buffer ring for provided buffers
io_uring_free_probe⚠
Free probe instance
io_uring_get_events⚠
Flush outstanding requests to CQE ring
io_uring_get_probe⚠
Get probe instance
io_uring_get_probe_ring⚠
Get probe information from an existing ring
io_uring_get_sqe⚠
Get the next available submission queue entry from the submission queue
io_uring_get_sqe128⚠
Get the next available 128-byte submission queue entry from the submission queue
io_uring_major_version⚠
Functions and macros to check the liburing version
io_uring_minor_version⚠
Functions and macros to check the liburing version
io_uring_opcode_supported⚠
Is op code supported?
io_uring_peek_batch_cqe⚠
Check if an io_uring completion event is available
io_uring_peek_cqe⚠
Check if an io_uring completion event is available
io_uring_prep_accept⚠
Prepare an accept request
io_uring_prep_accept_direct⚠
Prepare an accept request
io_uring_prep_bind⚠
Prepare a bind request
io_uring_prep_cancel⚠
Prepare a cancelation request
io_uring_prep_cancel64⚠
Prepare a cancelation request
io_uring_prep_cancel_fd⚠
Prepare a cancelation request
io_uring_prep_close⚠
Prepare a file descriptor close request
io_uring_prep_close_direct⚠
Prepare a file descriptor close request
io_uring_prep_cmd_discard⚠
Prepare a discard command
io_uring_prep_cmd_getsockname⚠
Prepare a getsockname or getpeername request
io_uring_prep_cmd_sock⚠
Prepare a command request for a socket
io_uring_prep_connect⚠
Prepare a connect request
io_uring_prep_epoll_ctl⚠
Prepare an epoll_ctl request
io_uring_prep_epoll_wait⚠
Prepare an epoll wait request
io_uring_prep_fadvise⚠
Prepare a fadvise request
io_uring_prep_fadvise64⚠
Prepare a fadvise request
io_uring_prep_fallocate⚠
Prepare a fallocate request
io_uring_prep_fgetxattr⚠
Prepare a request to get an extended attribute value
io_uring_prep_files_update⚠
Prepare a registered file update request
io_uring_prep_fixed_fd_install⚠
Prepare fixed file fd installation request
io_uring_prep_fsetxattr⚠
Prepare a request to set an extended attribute value
io_uring_prep_fsync⚠
Prepare an fsync request
io_uring_prep_ftruncate⚠
Prepare an ftruncate request
io_uring_prep_futex_wait⚠
Prepare a futex wait request
io_uring_prep_futex_waitv⚠
Prepare a futex waitv request
io_uring_prep_futex_wake⚠
Prepare a futex wake request
io_uring_prep_getxattr⚠
Prepare a request to get an extended attribute value
io_uring_prep_link⚠
Prepare a linkat request
io_uring_prep_link_timeout⚠
A timeout request for linked sqes
io_uring_prep_linkat⚠
Prepare a linkat request
io_uring_prep_listen⚠
Prepare a listen request
io_uring_prep_madvise⚠
Prepare a madvise request
io_uring_prep_madvise64⚠
Prepare a madvise request
io_uring_prep_mkdir⚠
Prepare an mkdirat request
io_uring_prep_mkdirat⚠
Prepare an mkdirat request
io_uring_prep_msg_ring⚠
Send a message to another ring
io_uring_prep_msg_ring_cqe_flags⚠
Send a message to another ring
io_uring_prep_msg_ring_fd⚠
Send a direct descriptor to another ring
io_uring_prep_msg_ring_fd_alloc⚠
Send a direct descriptor to another ring
io_uring_prep_multishot_accept⚠
Prepare an accept request
io_uring_prep_multishot_accept_direct⚠
Prepare an accept request
io_uring_prep_nop⚠
Prepare a nop request
io_uring_prep_nop128⚠
Prepare a nop request
io_uring_prep_open⚠
Prepare an openat request
io_uring_prep_open_direct⚠
Prepare an openat request
io_uring_prep_openat⚠
Prepare an openat request
io_uring_prep_openat2⚠
Prepare an openat2 request
io_uring_prep_openat2_direct⚠
Prepare an openat2 request
io_uring_prep_openat_direct⚠
Prepare an openat request
io_uring_prep_pipe⚠
Prepare a pipe creation request
io_uring_prep_pipe_direct⚠
Prepare a pipe creation request
io_uring_prep_poll_add⚠
Prepare a poll request
io_uring_prep_poll_multishot⚠
Prepare a poll request
io_uring_prep_poll_remove⚠
Prepare a poll deletion request
io_uring_prep_poll_update⚠
Update an existing poll request
io_uring_prep_provide_buffers⚠
Prepare a provide buffers request
io_uring_prep_read⚠
Prepare I/O read request
io_uring_prep_read_fixed⚠
Prepare I/O read request with registered buffer
io_uring_prep_read_multishot⚠
Prepare I/O read multishot request
io_uring_prep_readv⚠
Prepare vector I/O read request
io_uring_prep_readv2⚠
Prepare vector I/O read request with flags
io_uring_prep_readv_fixed⚠
Prepare a vectored read using fixed buffers
io_uring_prep_recv⚠
Prepare a recv request
io_uring_prep_recv_multishot⚠
Prepare a recv request
io_uring_prep_recvmsg⚠
Prepare a recvmsg request
io_uring_prep_recvmsg_multishot⚠
Prepare a recvmsg request
io_uring_prep_remove_buffers⚠
Prepare a remove buffers request
io_uring_prep_rename⚠
Prepare a renameat request
io_uring_prep_renameat⚠
Prepare a renameat request
io_uring_prep_send⚠
Prepare a send request
io_uring_prep_send_bundle⚠
Prepare a send request
io_uring_prep_send_set_addr⚠
Set address details for send requests
io_uring_prep_send_zc⚠
Prepare a zerocopy send request
io_uring_prep_send_zc_fixed⚠
Prepare a zerocopy send request
io_uring_prep_sendmsg⚠
Prepare a sendmsg request
io_uring_prep_sendmsg_zc⚠
Prepare a sendmsg request
io_uring_prep_sendmsg_zc_fixed⚠
Prepare a zero-copy sendmsg using fixed buffers
io_uring_prep_sendto⚠
Prepare a send request
io_uring_prep_setxattr⚠
Prepare a request to set an extended attribute value
io_uring_prep_shutdown⚠
Prepare a shutdown request
io_uring_prep_socket⚠
Prepare a socket creation request
io_uring_prep_socket_direct⚠
Prepare a socket creation request
io_uring_prep_socket_direct_alloc⚠
Prepare a socket creation request
io_uring_prep_splice⚠
Prepare an splice request
io_uring_prep_statx⚠
Prepare a statx request
io_uring_prep_symlink⚠
Prepare a symlinkat request
io_uring_prep_symlinkat⚠
Prepare a symlinkat request
io_uring_prep_sync_file_range⚠
Prepare a sync_file_range request
io_uring_prep_tee⚠
Prepare a tee request
io_uring_prep_timeout⚠
Prepare a timeout request
io_uring_prep_timeout_remove⚠
Prepare a request to update an existing timeout
io_uring_prep_timeout_update⚠
Prepare a request to update an existing timeout
io_uring_prep_unlink⚠
Prepare an unlinkat request
io_uring_prep_unlinkat⚠
Prepare an unlinkat request
io_uring_prep_uring_cmd⚠
Prepare a uring_cmd request
io_uring_prep_uring_cmd128⚠
Prepare a uring_cmd request
io_uring_prep_waitid⚠
Prepare a waitid request
io_uring_prep_write⚠
Prepare I/O write request
io_uring_prep_write_fixed⚠
Prepare I/O write request with registered buffer
io_uring_prep_writev⚠
Prepare vector I/O write request
io_uring_prep_writev2⚠
Prepare vector I/O write request with flags
io_uring_prep_writev_fixed⚠
Prepare a vectored write using fixed buffers
io_uring_queue_exit⚠
Tear down io_uring submission and completion queues
io_uring_queue_init⚠
Setup io_uring submission and completion queues
io_uring_queue_init_mem⚠
Setup io_uring submission and completion queues
io_uring_queue_init_params⚠
Setup io_uring submission and completion queues
io_uring_queue_mmap⚠
Mmap io_uring ring after setup
io_uring_recvmsg_cmsg_firsthdr⚠
Access data from multishot recvmsg
io_uring_recvmsg_cmsg_nexthdr⚠
Access data from multishot recvmsg
io_uring_recvmsg_name⚠
Access data from multishot recvmsg
io_uring_recvmsg_payload⚠
Access data from multishot recvmsg
io_uring_recvmsg_payload_length⚠
Access data from multishot recvmsg
io_uring_recvmsg_validate⚠
Access data from multishot recvmsg
io_uring_register⚠
Register files or user buffers for asynchronous I/O
io_uring_register_bpf_filter⚠
Register classic BPF filters for io_uring operations
io_uring_register_bpf_filter_task⚠
Register classic BPF filters for io_uring operations
io_uring_register_buf_ring⚠
Register buffer ring for provided buffers
io_uring_register_buffers⚠
Register buffers for fixed buffer operations
io_uring_register_buffers_sparse⚠
Register buffers for fixed buffer operations
io_uring_register_buffers_tags⚠
Register buffers for fixed buffer operations
io_uring_register_buffers_update_tag⚠
Register buffers for fixed buffer operations
io_uring_register_clock⚠
Set clock source for event waiting
io_uring_register_eventfd⚠
Register an eventfd with a ring
io_uring_register_eventfd_async⚠
Register an eventfd with a ring
io_uring_register_file_alloc_range⚠
Set range for fixed file allocations
io_uring_register_files⚠
Register file descriptors
io_uring_register_files_sparse⚠
Register file descriptors
io_uring_register_files_tags⚠
Register file descriptors
io_uring_register_files_update⚠
Register file descriptors
io_uring_register_files_update_tag⚠
Register file descriptors
io_uring_register_ifq⚠
Register a zero-copy receive interface queue
io_uring_register_iowq_aff⚠gnu
Register async worker CPU affinities
io_uring_register_iowq_max_workers⚠
Modify the maximum allowed async workers
io_uring_register_napi⚠
Register NAPI busy poll settings
io_uring_register_personality⚠
Register credentials with io_uring
io_uring_register_probe⚠
Register probe with io_uring
io_uring_register_query⚠
Query io_uring capabilities and feature support
io_uring_register_region⚠
Register a memory region
io_uring_register_restrictions⚠
Register restrictions with io_uring
io_uring_register_ring_fd⚠
Register a ring file descriptor
io_uring_register_sync_cancel⚠
Issue a synchronous cancelation request
io_uring_register_sync_msg⚠
Send a synchronous message to another ring
io_uring_register_wait_reg⚠
Register wait regions with io_uring
io_uring_register_zcrx_ctrl⚠
Perform control operations on a zero-copy receive context
io_uring_resize_rings⚠
Resize the SQ and CQ rings
io_uring_ring_dontfork⚠
Prevent ring memory from being shared after fork
io_uring_setup⚠
Setup a context for performing asynchronous I/O
io_uring_setup_buf_ring⚠
Setup and register buffer ring for provided buffers
io_uring_sq_ready⚠
Number of unconsumed or unsubmitted entries in the SQ ring
io_uring_sq_space_left⚠
Free space in the SQ ring
io_uring_sqe_set_buf_group⚠
Set buf group for submission queue event
io_uring_sqe_set_data⚠
Set user data for submission queue event
io_uring_sqe_set_data64⚠
Set user data for submission queue event
io_uring_sqe_set_flags⚠
Set flags for submission queue entry
io_uring_sqring_wait⚠
Wait for free space in the SQ ring
io_uring_submit⚠
Submit requests to the submission queue
io_uring_submit_and_get_events⚠
Submit requests to the submission queue and flush completions
io_uring_submit_and_wait⚠
Submit requests to the submission queue and wait for completion
io_uring_submit_and_wait_min_timeout⚠
Submit requests to the submission queue and wait for the completion with both batch and normal timeout
io_uring_submit_and_wait_reg⚠
Sets up and registers fixed wait regions
io_uring_submit_and_wait_timeout⚠
Submit requests to the submission queue and wait for the completion with timeout
io_uring_unregister_buf_ring⚠
Unregister a previously registered buffer ring
io_uring_unregister_buffers⚠
Unregister buffers for fixed buffer operations
io_uring_unregister_eventfd⚠
Register an eventfd with a ring
io_uring_unregister_files⚠
Unregister file descriptors
io_uring_unregister_iowq_aff⚠
Register async worker CPU affinities
io_uring_unregister_napi⚠
Unregister NAPI busy poll settings
io_uring_unregister_personality⚠
Unregister a personality from io_uring
io_uring_unregister_ring_fd⚠
Unregister a ring file descriptor
io_uring_wait_cqe⚠
Wait for one io_uring completion event
io_uring_wait_cqe_nr⚠
Wait for one or more io_uring completion events
io_uring_wait_cqe_timeout⚠
Wait for one io_uring completion event with timeout
io_uring_wait_cqes⚠
Wait for one or more io_uring completion events
io_uring_wait_cqes_min_timeout⚠
Wait for completions with both batch and normal timeout