Commit a3e4bc23 authored by Jens Axboe's avatar Jens Axboe

io_uring: defer splice/tee file validity check until command issue

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: default avatarJens Axboe <axboe@kernel.dk>
parent ec858afd
...@@ -654,10 +654,10 @@ struct io_epoll { ...@@ -654,10 +654,10 @@ struct io_epoll {
struct io_splice { struct io_splice {
struct file *file_out; struct file *file_out;
struct file *file_in;
loff_t off_out; loff_t off_out;
loff_t off_in; loff_t off_in;
u64 len; u64 len;
int splice_fd_in;
unsigned int flags; unsigned int flags;
}; };
...@@ -1687,14 +1687,6 @@ static void io_prep_async_work(struct io_kiocb *req) ...@@ -1687,14 +1687,6 @@ static void io_prep_async_work(struct io_kiocb *req)
if (def->unbound_nonreg_file) if (def->unbound_nonreg_file)
req->work.flags |= IO_WQ_WORK_UNBOUND; 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) static void io_prep_async_link(struct io_kiocb *req)
...@@ -4369,18 +4361,11 @@ static int __io_splice_prep(struct io_kiocb *req, ...@@ -4369,18 +4361,11 @@ static int __io_splice_prep(struct io_kiocb *req,
if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
return -EINVAL; return -EINVAL;
sp->file_in = NULL;
sp->len = READ_ONCE(sqe->len); sp->len = READ_ONCE(sqe->len);
sp->flags = READ_ONCE(sqe->splice_flags); sp->flags = READ_ONCE(sqe->splice_flags);
if (unlikely(sp->flags & ~valid_flags)) if (unlikely(sp->flags & ~valid_flags))
return -EINVAL; return -EINVAL;
sp->splice_fd_in = READ_ONCE(sqe->splice_fd_in);
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;
return 0; return 0;
} }
...@@ -4395,20 +4380,27 @@ static int io_tee_prep(struct io_kiocb *req, ...@@ -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) static int io_tee(struct io_kiocb *req, unsigned int issue_flags)
{ {
struct io_splice *sp = &req->splice; struct io_splice *sp = &req->splice;
struct file *in = sp->file_in;
struct file *out = sp->file_out; struct file *out = sp->file_out;
unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED; unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
struct file *in;
long ret = 0; long ret = 0;
if (issue_flags & IO_URING_F_NONBLOCK) if (issue_flags & IO_URING_F_NONBLOCK)
return -EAGAIN; 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) if (sp->len)
ret = do_tee(in, out, sp->len, flags); ret = do_tee(in, out, sp->len, flags);
if (!(sp->flags & SPLICE_F_FD_IN_FIXED)) if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
io_put_file(in); io_put_file(in);
req->flags &= ~REQ_F_NEED_CLEANUP; done:
if (ret != sp->len) if (ret != sp->len)
req_set_fail(req); req_set_fail(req);
io_req_complete(req, ret); io_req_complete(req, ret);
...@@ -4427,15 +4419,22 @@ static int io_splice_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) ...@@ -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) static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
{ {
struct io_splice *sp = &req->splice; struct io_splice *sp = &req->splice;
struct file *in = sp->file_in;
struct file *out = sp->file_out; struct file *out = sp->file_out;
unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED; unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED;
loff_t *poff_in, *poff_out; loff_t *poff_in, *poff_out;
struct file *in;
long ret = 0; long ret = 0;
if (issue_flags & IO_URING_F_NONBLOCK) if (issue_flags & IO_URING_F_NONBLOCK)
return -EAGAIN; 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_in = (sp->off_in == -1) ? NULL : &sp->off_in;
poff_out = (sp->off_out == -1) ? NULL : &sp->off_out; poff_out = (sp->off_out == -1) ? NULL : &sp->off_out;
...@@ -4444,8 +4443,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags) ...@@ -4444,8 +4443,7 @@ static int io_splice(struct io_kiocb *req, unsigned int issue_flags)
if (!(sp->flags & SPLICE_F_FD_IN_FIXED)) if (!(sp->flags & SPLICE_F_FD_IN_FIXED))
io_put_file(in); io_put_file(in);
req->flags &= ~REQ_F_NEED_CLEANUP; done:
if (ret != sp->len) if (ret != sp->len)
req_set_fail(req); req_set_fail(req);
io_req_complete(req, ret); io_req_complete(req, ret);
...@@ -7176,11 +7174,6 @@ static void io_clean_op(struct io_kiocb *req) ...@@ -7176,11 +7174,6 @@ static void io_clean_op(struct io_kiocb *req)
kfree(io->free_iov); kfree(io->free_iov);
break; 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_OPENAT:
case IORING_OP_OPENAT2: case IORING_OP_OPENAT2:
if (req->open.filename) if (req->open.filename)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment