axboe / liburing

Library providing helpers for the Linux kernel io_uring support
MIT License
2.7k stars 393 forks source link

io_uring_register_files() always failed with bad file descriptor error (EBADF) #1172

Closed ytwang3579 closed 1 week ago

ytwang3579 commented 2 weeks ago

Hi, I was trying to use io_uring with SQPOLL mode for a simple network server example. When I tried to register fd with io_uring_register_files(), I am constantly getting "Bad file descriptor" error. I was doing the initialization of io_uring with the following code:

    struct io_uring ring;
    struct io_uring_params params;

    std::memset(&params, 0, sizeof(params));
    params.flags |= IORING_SETUP_SQPOLL;

    int res = io_uring_queue_init_params(QUEUE_DEPTH, &ring, &params);
    if (res < 0) {
        std::cerr << "Failed to initialize io_uring:" << std::strerror(-res) << "\n";
        close(server_fd);
        return 1;
    }

    res = io_uring_register_files(&ring, &server_fd, 1);
    if (res < 0) {
        std::cerr << "Failed to register file descriptor: " << std::strerror(-res) << "\n";
        close(server_fd);
        return 1;
    }

Always getting the following error:

Failed to register file descriptor: Bad file descriptor

The server example is working without SQPOLL mode. I was trying to register the server_fd to get familiar with the SQPOLL feature. Am I doing anything wrong here?

I also tried running the tests provided using sudo make runtests, and it seems like the fds are not able to be registered in all the tests, giving the same -EBADF (-9) error:

Running test 232c93d07b74.t                                         5 sec
Running test 35fa71a030ca.t                                         5 sec
Running test 500f9fbadef8.t                                         0 sec
Running test 7ad0e4b2f83c.t                                         1 sec
Running test 8a9973408177.t                                         file register -9
Test 8a9973408177.t failed with ret 1

...(truncated)...

Running test d4ae271dfaae.t                                         register files -9
Test d4ae271dfaae.t failed with ret 247

...(truncated)...

Running test fd-install.t                                           failed register files -9
test_working failed
Test fd-install.t failed with ret 1
Running test fd-pass.t                                              Skipped
Running test file-register.t                                        test_basic: register -9
test_basic failed
Test file-register.t failed with ret 1
Running test files-exit-hang-poll.t                                 1 sec
Running test files-exit-hang-timeout.t                              1 sec
Running test file-update.t                                          test_update_multiring: register files failed
test_update_multiring w/unreg
Test file-update.t failed with ret 1

...(truncated)...

Running test iopoll.t                                               file reg failed: -9
test_io failed 0/1/0/0/0
Test iopoll.t failed with ret 1

...(truncated)...

What are the requirements for io_uring_register_files() to work? I was only seeing kernel version >= 5.1 here. Thanks in advance!

Full test log: io_uring_test_result.txt Environment (both failed):

RogerMarcoHernandez commented 1 week ago

Hi @ytwang3579,

After investigating, turns out this was a bug in Ubuntu 22.04 LTS kernel, specifically in Ubuntu-5.15.0-113.123 (the Ubuntu 22.04 LTS current default kernel) and I assume also in previous versions. In fact, it was fixed by @axboe in Ubuntu-5.15.0-115.125 on this commit.

The problem was not returning an exit code (0) on success and instead returning the previously assigned error value for the return variable.

I guess the solution to your case is to update to a newer Ubuntu version with the kernel Ubuntu-5.15.0-115.125 or above.

axboe commented 1 week ago

Sorry missed this - yes indeed like @RogerMarcoHernandez says, this is a kernel bug in the distro kernel you are using. If you upgrade, it should be fine. In terms of the stable series of 5.x kernels, 5.4 will be too ancient for you, but 5.10 or 5.15 based should be OK for SQPOLL and registered files.

In general, as per usual, I always recommend people at least run a 6.x based kernel.