Skip to content

Commit

Permalink
io_uring: defer splice/tee file validity check until command issue
Browse files Browse the repository at this point in the history
In preparation for not using the file at prep time, defer checking if this
file refers to a valid io_uring instance until issue time.

This also means we can get rid of the cleanup flag for splice and tee.

Cc: stable@vger.kernel.org # v5.15+
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Jens Axboe committed Apr 4, 2022
1 parent ec858af commit a3e4bc2
Showing 1 changed file with 21 additions and 28 deletions.
49 changes: 21 additions & 28 deletions fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,10 +654,10 @@ struct io_epoll {

struct io_splice {
struct file *file_out;
struct file *file_in;
loff_t off_out;
loff_t off_in;
u64 len;
int splice_fd_in;
unsigned int flags;
};

Expand Down Expand Up @@ -1687,14 +1687,6 @@ static void io_prep_async_work(struct io_kiocb *req)
if (def->unbound_nonreg_file)
req->work.flags |= IO_WQ_WORK_UNBOUND;
}

switch (req->opcode) {
case IORING_OP_SPLICE:
case IORING_OP_TEE:
if (!S_ISREG(file_inode(req->splice.file_in)->i_mode))
req->work.flags |= IO_WQ_WORK_UNBOUND;
break;
}
}

static void io_prep_async_link(struct io_kiocb *req)
Expand Down Expand Up @@ -4369,18 +4361,11 @@ static int __io_splice_prep(struct io_kiocb *req,
if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
return -EINVAL;

sp->file_in = NULL;
sp->len = READ_ONCE(sqe->len);
sp->flags = READ_ONCE(sqe->splice_flags);

if (unlikely(sp->flags & ~valid_flags))
return -EINVAL;

sp->file_in = io_file_get(req->ctx, req, READ_ONCE(sqe->splice_fd_in),
(sp->flags & SPLICE_F_FD_IN_FIXED));
if (!sp->file_in)
return -EBADF;
req->flags |= REQ_F_NEED_CLEANUP;
sp->splice_fd_in = READ_ONCE(sqe->splice_fd_in);
return 0;
}

Expand All @@ -4395,20 +4380,27 @@ static int io_tee_prep(struct io_kiocb *req,
static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_splice *sp = &req->splice;
struct file *in = sp->file_in;
struct file *out = sp->file_out;
unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
struct file *in;
long ret = 0;

if (issue_flags & IO_URING_F_NONBLOCK)
return -EAGAIN;

in = io_file_get(req->ctx, req, sp->splice_fd_in,
(sp->flags & SPLICE_F_FD_IN_FIXED));
if (!in) {
ret = -EBADF;
goto done;
}

if (sp->len)
ret = do_tee(in, out, sp->len, flags);

if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
io_put_file(in);
req->flags &= ~REQ_F_NEED_CLEANUP;

done:
if (ret != sp->len)
req_set_fail(req);
io_req_complete(req, ret);
Expand All @@ -4427,15 +4419,22 @@ static int io_splice_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_splice *sp = &req->splice;
struct file *in = sp->file_in;
struct file *out = sp->file_out;
unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
loff_t *poff_in, *poff_out;
struct file *in;
long ret = 0;

if (issue_flags & IO_URING_F_NONBLOCK)
return -EAGAIN;

in = io_file_get(req->ctx, req, sp->splice_fd_in,
(sp->flags & SPLICE_F_FD_IN_FIXED));
if (!in) {
ret = -EBADF;
goto done;
}

poff_in = (sp->off_in == -1) ? NULL : &sp->off_in;
poff_out = (sp->off_out == -1) ? NULL : &sp->off_out;

Expand All @@ -4444,8 +4443,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)

if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
io_put_file(in);
req->flags &= ~REQ_F_NEED_CLEANUP;

done:
if (ret != sp->len)
req_set_fail(req);
io_req_complete(req, ret);
Expand Down Expand Up @@ -7176,11 +7174,6 @@ static void io_clean_op(struct io_kiocb *req)
kfree(io->free_iov);
break;
}
case IORING_OP_SPLICE:
case IORING_OP_TEE:
if (!(req->splice.flags & SPLICE_F_FD_IN_FIXED))
io_put_file(req->splice.file_in);
break;
case IORING_OP_OPENAT:
case IORING_OP_OPENAT2:
if (req->open.filename)
Expand Down

0 comments on commit a3e4bc2

Please sign in to comment.