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: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
ec858afda8
commit
a3e4bc23d5
@ -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;
|
||||
};
|
||||
|
||||
@ -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)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user