All Products
Search
Document Center

Alibaba Cloud Linux:Use the io_uring percpu sqthread feature

Last Updated:May 20, 2025

This topic describes how to use the io_uring percpu sqthread feature and handle common error codes.

Background

io_uring is a high-performance asynchronous I/O interface in the Linux kernel that uses a pair of shared memory buffers (ring buffers) to implement efficient communication between applications and the kernel, thereby improving performance and efficiency. sqpoll is an io_uring feature that enables a separate kernel thread to process tasks in the submission queue (SQ). The thread is called sqthread.

If multiple io_uring instances are created in the same process with sqpoll enabled, all sqthreads may run on the same CPU core. Each io_uring instance starts a separate sqthread. As such, multiple sqthreads simultaneously run on a single core, and sqthread context switching incurs unnecessary overhead. To implement efficient sqpoll functionality and reduce usage complexity, Alibaba Cloud Linux 3 provides the io_uring percpu sqthread feature, which allows you to specify the core on which an sqthread runs during thread creation. Additionally, only one sqthread can exist on each core, and this sqthread polls and processes requests from all io_uring instances bound to it.

Limits

Operating system: Alibaba Cloud Linux 3.

Kernel version: 5.10.112-11 or later.

Use the percpu sqthread feature

Enable the percpu sqthread feature

When initializing io_uring, set the IORING_SETUP_SQPOLL flag to enable the sqpoll mode. To enable the percpu sqthread feature, configure IORING_SETUP_SQPOLL_PERCPU and IORING_SETUP_SQ_AFF and specify the ordinal number of the CPU where the sqthread is located for sq_thread_cpu. Sample code:

struct io_uring ring;
struct io_uring_params params = {};
params.flags = IORING_SETUP_SQPOLL|IORING_SETUP_SQPOLL_PERCPU|IORING_SETUP_SQ_AFF;
params.sq_thread_cpu = 1;
ret = io_uring_queue_init_params(ENTRIES, &ring, &params);
if (ret < 0) {
    perror("io_uring_queue_init_params");
    exit(EXIT_FAILURE);
}

Submit and process I/O requests

  1. Use the io_uring_sqe struct to prepare I/O requests.

    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    if (!sqe) {
        fprintf(stderr, "get sqe failed\n");
        return -1;
    }
    io_uring_prep_read(sqe, fd, buf, len, offset);
    sqe->user_data = (uint64_t)buf;
  2. Use the io_uring_submit function to submit requests to the SQ.

    ret = io_uring_submit(&ring);
    if (ret < 0) {
        perror("io_uring_submit");
        return -1;
    }
  3. Use the io_uring_wait_cqe or io_uring_peek_cqe function to retrieve completed I/O requests from the completion queue (CQ).

    struct io_uring_cqe *cqe;
    ret = io_uring_wait_cqe(&ring, &cqe);
    if (ret < 0) {
        perror("io_uring_wait_cqe");
        return -1;
    }
    if (cqe->res < 0) {
        fprintf(stderr, "read error: %s\n", strerror(-cqe->res));
    } else {
        printf("read %d bytes\n", cqe->res);
    }
    io_uring_cqe_seen(&ring, cqe);

FAQ

Q1: What do I do if error code -1 (Operation Not Permitted) is returned when I create an io_uring instance?

For example, when you call the __sys_io_uring_setup function to create an io_uring instance, the return value is -1 (EPERM).

Cause and solution

The current process is different from the process that initially created the sqthread on the CPU. The percpu sqthread feature only supports sqthread sharing within a process. If Process A first creates an sqthread on CPU X, only different threads of the same process can share that sqthread. In this case, if you want Process B to use the feature, select a different CPU to bind.

Q2: What do I do if code -22 (invalid parameter) is returned when I create an io_uring instance?

For example, when you call __sys_io_uring_setup function to create an io_uring instance, the return value is -22 (EINVAL).

Cause and solution

In this case, check whether the sq_thread_cpu parameter is valid. The sq_thread_cpu parameter specifies the number of the CPU where the sqthread bound to the io_uring instance is located. The CPU number must be valid, which is smaller than or equal to the cpu_num value, and the specified CPU must be in the online state.

  1. Check whether the CPU is online.

    cat /sys/devices/system/cpu/online
  2. If the number of the bound CPU is not in the list of online CPUs, enable the CPU or bind a different CPU.

    For example, run the following command to enable CPU 1:

    sudo sh -c 'echo 1 > /sys/devices/system/cpu/cpu1/online'