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 io_open {
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int dfd;
|
int dfd;
|
||||||
|
bool ignore_nonblock;
|
||||||
struct filename *filename;
|
struct filename *filename;
|
||||||
struct open_how how;
|
struct open_how how;
|
||||||
unsigned long nofile;
|
unsigned long nofile;
|
||||||
@ -3796,6 +3797,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
req->open.nofile = rlimit(RLIMIT_NOFILE);
|
req->open.nofile = rlimit(RLIMIT_NOFILE);
|
||||||
|
req->open.ignore_nonblock = false;
|
||||||
req->flags |= REQ_F_NEED_CLEANUP;
|
req->flags |= REQ_F_NEED_CLEANUP;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3839,7 +3841,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
|
|||||||
struct file *file;
|
struct file *file;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (force_nonblock)
|
if (force_nonblock && !req->open.ignore_nonblock)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
ret = build_open_flags(&req->open.how, &op);
|
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)) {
|
if (IS_ERR(file)) {
|
||||||
put_unused_fd(ret);
|
put_unused_fd(ret);
|
||||||
ret = PTR_ERR(file);
|
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 {
|
} else {
|
||||||
fsnotify_open(file);
|
fsnotify_open(file);
|
||||||
fd_install(ret, file);
|
fd_install(ret, file);
|
||||||
|
Loading…
Reference in New Issue
Block a user