Search code examples
linuxaioblock-device

How to check block device supports `nowait` or not


I want to use async IO in my program. After some searching, I found nowait was added to avoid the blocking in aio. How can I check my system(block-device、plug, etc) supports nowait or not?

I am using ubuntu 22.04 with kernel version 6.2.6


Solution

  • The short answer is that today, you can't tell if a device supports NOWAIT I/O.

    Inside the kernel, the block device queue will be tagged with QUEUE_FLAG_NOWAIT if it supports NOWAIT I/O. You can query the flag state with blk_queue_nowait. But, the flag isn't exposed to user space. (It'd be a trivial patch though.)

    That leaves you with trying to develop some sort of probe for NOWAIT support, but I'm afraid there isn't a straightforward answer there either.

    • Nobody thought ahead to add a "reserved" section in the AIO iocb structure way back, so there's no way for older kernels that don't know about NOWAIT to say "no, I don't support this flag." The flag just goes into the kernel and the kernel ignores it.
    • Even in new kernels, when you specify NOWAIT, there's no "I don't support this" error return. Instead, a few things can happen:
    1. Most devices that lack support for it may simply return EAGAIN forever. So, that's one probe you can try: do NOWAIT reads and see if the device ever handles one of them.
    2. Some devices just ignore the flag. It will be as if you were doing NOWAIT I/O on an older kernel with occasional blocking io_submit calls.
    3. The devices that support NOWAIT I/O will complete the I/O's nearly all the time, but occasionally return EAGAIN. That's what you're looking for. If you occasionally see EAGAIN, that indicates that NOWAIT is probably working.

    I would offer that you might not need to worry about NOWAIT for a new application right off the bat. Plan for io_submit to block for a few tens of microseconds. If need be, put the I/O handling in its own thread.