Skip to content

Commit 944d144

Browse files
committed
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>
1 parent 8d4c3e7 commit 944d144

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

fs/io_uring.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ struct io_sr_msg {
478478
struct io_open {
479479
struct file *file;
480480
int dfd;
481+
bool ignore_nonblock;
481482
struct filename *filename;
482483
struct open_how how;
483484
unsigned long nofile;
@@ -3796,6 +3797,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
37963797
return ret;
37973798
}
37983799
req->open.nofile = rlimit(RLIMIT_NOFILE);
3800+
req->open.ignore_nonblock = false;
37993801
req->flags |= REQ_F_NEED_CLEANUP;
38003802
return 0;
38013803
}
@@ -3839,7 +3841,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
38393841
struct file *file;
38403842
int ret;
38413843

3842-
if (force_nonblock)
3844+
if (force_nonblock && !req->open.ignore_nonblock)
38433845
return -EAGAIN;
38443846

38453847
ret = build_open_flags(&req->open.how, &op);
@@ -3854,6 +3856,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
38543856
if (IS_ERR(file)) {
38553857
put_unused_fd(ret);
38563858
ret = PTR_ERR(file);
3859+
/*
3860+
* A work-around to ensure that /proc/self works that way
3861+
* that it should - if we get -EOPNOTSUPP back, then assume
3862+
* that proc_self_get_link() failed us because we're in async
3863+
* context. We should be safe to retry this from the task
3864+
* itself with force_nonblock == false set, as it should not
3865+
* block on lookup. Would be nice to know this upfront and
3866+
* avoid the async dance, but doesn't seem feasible.
3867+
*/
3868+
if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) {
3869+
req->open.ignore_nonblock = true;
3870+
refcount_inc(&req->refs);
3871+
io_req_task_queue(req);
3872+
return 0;
3873+
}
38573874
} else {
38583875
fsnotify_open(file);
38593876
fd_install(ret, file);

0 commit comments

Comments
 (0)