Commit 944d1444 authored by Jens Axboe's avatar Jens Axboe
Browse files

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: default avatarJens Axboe <axboe@kernel.dk>
parent 8d4c3e76
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -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);