mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
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 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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user