Commit 8da11c19 authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe
Browse files

io_uring: add interface for getting files



Preparation without functional changes. Adds io_get_file(), that allows
to grab files not only into req->file.

Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 444ebb57
Loading
Loading
Loading
Loading
+43 −29
Original line number Diff line number Diff line
@@ -1253,6 +1253,15 @@ fallback:
	return NULL;
}

static inline void io_put_file(struct io_kiocb *req, struct file *file,
			  bool fixed)
{
	if (fixed)
		percpu_ref_put(&req->ctx->file_data->refs);
	else
		fput(file);
}

static void __io_req_do_free(struct io_kiocb *req)
{
	if (likely(!io_is_fallback_req(req)))
@@ -1263,18 +1272,12 @@ static void __io_req_do_free(struct io_kiocb *req)

static void __io_req_aux_free(struct io_kiocb *req)
{
	struct io_ring_ctx *ctx = req->ctx;

	if (req->flags & REQ_F_NEED_CLEANUP)
		io_cleanup_req(req);

	kfree(req->io);
	if (req->file) {
		if (req->flags & REQ_F_FIXED_FILE)
			percpu_ref_put(&ctx->file_data->refs);
		else
			fput(req->file);
	}
	if (req->file)
		io_put_file(req, req->file, (req->flags & REQ_F_FIXED_FILE));

	io_req_work_drop_env(req);
}
@@ -1848,7 +1851,7 @@ static void io_file_put(struct io_submit_state *state)
 * assuming most submissions are for one file, or at least that each file
 * has more than one submission.
 */
static struct file *io_file_get(struct io_submit_state *state, int fd)
static struct file *__io_file_get(struct io_submit_state *state, int fd)
{
	if (!state)
		return fget(fd);
@@ -4578,41 +4581,52 @@ static inline struct file *io_file_from_index(struct io_ring_ctx *ctx,
	return table->files[index & IORING_FILE_TABLE_MASK];;
}

static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
			   const struct io_uring_sqe *sqe)
static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
			int fd, struct file **out_file, bool fixed)
{
	struct io_ring_ctx *ctx = req->ctx;
	unsigned flags;
	int fd;

	flags = READ_ONCE(sqe->flags);
	fd = READ_ONCE(sqe->fd);

	if (!io_req_needs_file(req, fd))
		return 0;
	struct file *file;

	if (flags & IOSQE_FIXED_FILE) {
	if (fixed) {
		if (unlikely(!ctx->file_data ||
		    (unsigned) fd >= ctx->nr_user_files))
			return -EBADF;
		fd = array_index_nospec(fd, ctx->nr_user_files);
		req->file = io_file_from_index(ctx, fd);
		if (!req->file)
		file = io_file_from_index(ctx, fd);
		if (!file)
			return -EBADF;
		req->flags |= REQ_F_FIXED_FILE;
		percpu_ref_get(&ctx->file_data->refs);
	} else {
		if (req->needs_fixed_file)
			return -EBADF;
		trace_io_uring_file_get(ctx, fd);
		req->file = io_file_get(state, fd);
		if (unlikely(!req->file))
		file = __io_file_get(state, fd);
		if (unlikely(!file))
			return -EBADF;
	}

	*out_file = file;
	return 0;
}

static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
			   const struct io_uring_sqe *sqe)
{
	unsigned flags;
	int fd;
	bool fixed;

	flags = READ_ONCE(sqe->flags);
	fd = READ_ONCE(sqe->fd);

	if (!io_req_needs_file(req, fd))
		return 0;

	fixed = (flags & IOSQE_FIXED_FILE);
	if (unlikely(!fixed && req->needs_fixed_file))
		return -EBADF;

	return io_file_get(state, req, fd, &req->file, fixed);
}

static int io_grab_files(struct io_kiocb *req)
{
	int ret = -EBADF;
@@ -4858,7 +4872,7 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,

	/* same numerical values with corresponding REQ_F_*, safe to copy */
	req->flags |= sqe_flags & (IOSQE_IO_DRAIN | IOSQE_IO_HARDLINK |
					IOSQE_ASYNC);
					IOSQE_ASYNC | IOSQE_FIXED_FILE);

	ret = io_req_set_file(state, req, sqe);
	if (unlikely(ret)) {