Axboe RFC: io_uring hands off thread identity on actual block
Instead of always punting blockable ops to io-wq, the series runs them inline and migrates only the user-visible identity if the submitter sleeps.
Jens Axboe has posted an RFC series that would let io_uring issue many currently offloaded operations inline, paying the worker cost only when a request actually blocks.
Today io_uring tries nonblocking issue first and punts to the io-wq pool when that is not possible. A large set of opcodes never has a nonblocking path at all: fsync, statx, openat and the *at family, xattr, fadvise, splice, and similar. Those are always handed to a worker, which means a wakeup, a context switch, and a task_work round trip even when the call would have completed immediately (an fdatasync that does not flush, a statx that hits dcache, an O_TMPFILE open, and so on). io_uring cannot risk accidental blocking in the submit path, so it has had no choice.
The series flips that tradeoff. Blockable opcodes are issued inline in blocking mode. If the request never sleeps, it finishes on the submitter with no offload. If it does sleep, a scheduler hook (PF_IO_HANDOFF) catches the block while the submitter still holds the uring lock. An idle io-wq worker then takes over the user-visible identity: tid, signal state, credentials, scheduling attributes, cgroup, and register state. That worker completes the io_uring_enter() call and returns to userspace as the original submitter. The blocked task finishes the request and joins the worker pool. From userspace, the same tid comes back from the syscall; only the underlying task_struct has changed.
The identity move is factored as generic kernel infrastructure (thread handoff), with architecture hooks first for x86-64 and arm64, plus io-wq claim logic so only a worker already in its idle sleep can be promoted. A later tweak in the series defers the full identity migration until the end of a multi-SQE submission, so intermediate hops only adopt credentials and the io_uring context. Ops that already have a working nonblocking path keep today’s behavior; SQEs explicitly marked async still force an io-wq punt. uring_cmd is left out for now because drivers may bind state to the submitting task.
Axboe notes earlier kernel attempts at similar identity handoff roughly two decades ago. The RFC is aimed at cutting avoidable latency and context-switch overhead for the many "might block" operations that usually do not.