io_uring: handle -EOPNOTSUPP on path resolution
Any attempt to do path resolution on /proc/self from an async worker will yield -EOPNOTSUPP. We can safely do that resolution from the task itself, and without blocking, so retry it from there. Ideally io_uring would know this upfront and not have to go through the worker thread to find out, but that doesn't currently seem feasible. Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
8d4c3e76e3
commit
944d1444d5
@ -478,6 +478,7 @@ struct io_sr_msg {
|
||||
struct io_open {
|
||||
struct file *file;
|
||||
int dfd;
|
||||
bool ignore_nonblock;
|
||||
struct filename *filename;
|
||||
struct open_how how;
|
||||
unsigned long nofile;
|
||||
@ -3796,6 +3797,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
||||
return ret;
|
||||
}
|
||||
req->open.nofile = rlimit(RLIMIT_NOFILE);
|
||||
req->open.ignore_nonblock = false;
|
||||
req->flags |= REQ_F_NEED_CLEANUP;
|
||||
return 0;
|
||||
}
|
||||
@ -3839,7 +3841,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
|
||||
struct file *file;
|
||||
int ret;
|
||||
|
||||
if (force_nonblock)
|
||||
if (force_nonblock && !req->open.ignore_nonblock)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = build_open_flags(&req->open.how, &op);
|
||||
@ -3854,6 +3856,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
|
||||
if (IS_ERR(file)) {
|
||||
put_unused_fd(ret);
|
||||
ret = PTR_ERR(file);
|
||||
/*
|
||||
* A work-around to ensure that /proc/self works that way
|
||||
* that it should - if we get -EOPNOTSUPP back, then assume
|
||||
* that proc_self_get_link() failed us because we're in async
|
||||
* context. We should be safe to retry this from the task
|
||||
* itself with force_nonblock == false set, as it should not
|
||||
* block on lookup. Would be nice to know this upfront and
|
||||
* avoid the async dance, but doesn't seem feasible.
|
||||
*/
|
||||
if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) {
|
||||
req->open.ignore_nonblock = true;
|
||||
refcount_inc(&req->refs);
|
||||
io_req_task_queue(req);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fsnotify_open(file);
|
||||
fd_install(ret, file);
|
||||
|
Loading…
Reference in New Issue
Block a user