On 02/04/2021 11:32, Pavel Begunkov wrote: > On 02/04/2021 09:52, Hao Xu wrote: >> 在 2021/4/1 下午10:57, Jens Axboe 写道: >>> S_ISBLK is marked as unbounded work for async preparation, because it >>> doesn't match S_ISREG. That is incorrect, as any read/write to a block >>> device is also a bounded operation. Fix it up and ensure that S_ISBLK >>> isn't marked unbounded. >>> >>> Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> >>> >> Hi Jens, I saw a (un)bounded work is for a (un)bounded worker to >> execute. What is the difference between bounded and unbounded? > > Unbounded works are not bounded in execution time, i.e. they may take > forever to complete. E.g. recv depends on the other end to send something, > that not necessarily will ever happen. To elaborate a bit, one example of how it's used: because unbounded may stay for long, it always spawns a new worker thread for each of them. If app submits SQEs as below, and send's are not actually sent for execution but stashed somewhere internally in a list, e.g. waiting for a worker thread to get free, it would just hang from the userspace perspective. recv(fd1), recv(fd1), send(fd1), send(fd1) >>> diff --git a/fs/io_uring.c b/fs/io_uring.c >>> index 6d7a1b69712b..a16b7df934d1 100644 >>> --- a/fs/io_uring.c >>> +++ b/fs/io_uring.c >>> @@ -1213,7 +1213,7 @@ static void io_prep_async_work(struct io_kiocb *req) >>> if (req->flags & REQ_F_ISREG) { >>> if (def->hash_reg_file || (ctx->flags & IORING_SETUP_IOPOLL)) >>> io_wq_hash_work(&req->work, file_inode(req->file)); >>> - } else { >>> + } else if (!req->file || !S_ISBLK(file_inode(req->file)->i_mode)) { >>> if (def->unbound_nonreg_file) >>> req->work.flags |= IO_WQ_WORK_UNBOUND; >>> } -- Pavel Begunkov