1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
5 #include <linux/file.h>
7 #include <linux/slab.h>
8 #include <linux/namei.h>
9 #include <linux/io_uring.h>
10 #include <linux/splice.h>
12 #include <uapi/linux/io_uring.h>
18 struct file
*file_out
;
24 struct io_rsrc_node
*rsrc_node
;
27 static int __io_splice_prep(struct io_kiocb
*req
,
28 const struct io_uring_sqe
*sqe
)
30 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
31 unsigned int valid_flags
= SPLICE_F_FD_IN_FIXED
| SPLICE_F_ALL
;
33 sp
->len
= READ_ONCE(sqe
->len
);
34 sp
->flags
= READ_ONCE(sqe
->splice_flags
);
35 if (unlikely(sp
->flags
& ~valid_flags
))
37 sp
->splice_fd_in
= READ_ONCE(sqe
->splice_fd_in
);
39 req
->flags
|= REQ_F_FORCE_ASYNC
;
43 int io_tee_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
45 if (READ_ONCE(sqe
->splice_off_in
) || READ_ONCE(sqe
->off
))
47 return __io_splice_prep(req
, sqe
);
50 void io_splice_cleanup(struct io_kiocb
*req
)
52 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
54 io_put_rsrc_node(req
->ctx
, sp
->rsrc_node
);
57 static struct file
*io_splice_get_file(struct io_kiocb
*req
,
58 unsigned int issue_flags
)
60 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
61 struct io_ring_ctx
*ctx
= req
->ctx
;
62 struct io_rsrc_node
*node
;
63 struct file
*file
= NULL
;
65 if (!(sp
->flags
& SPLICE_F_FD_IN_FIXED
))
66 return io_file_get_normal(req
, sp
->splice_fd_in
);
68 io_ring_submit_lock(ctx
, issue_flags
);
69 node
= io_rsrc_node_lookup(&ctx
->file_table
.data
, sp
->splice_fd_in
);
73 file
= io_slot_file(node
);
74 req
->flags
|= REQ_F_NEED_CLEANUP
;
76 io_ring_submit_unlock(ctx
, issue_flags
);
80 int io_tee(struct io_kiocb
*req
, unsigned int issue_flags
)
82 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
83 struct file
*out
= sp
->file_out
;
84 unsigned int flags
= sp
->flags
& ~SPLICE_F_FD_IN_FIXED
;
88 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
90 in
= io_splice_get_file(req
, issue_flags
);
97 ret
= do_tee(in
, out
, sp
->len
, flags
);
99 if (!(sp
->flags
& SPLICE_F_FD_IN_FIXED
))
104 io_req_set_res(req
, ret
, 0);
108 int io_splice_prep(struct io_kiocb
*req
, const struct io_uring_sqe
*sqe
)
110 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
112 sp
->off_in
= READ_ONCE(sqe
->splice_off_in
);
113 sp
->off_out
= READ_ONCE(sqe
->off
);
114 return __io_splice_prep(req
, sqe
);
117 int io_splice(struct io_kiocb
*req
, unsigned int issue_flags
)
119 struct io_splice
*sp
= io_kiocb_to_cmd(req
, struct io_splice
);
120 struct file
*out
= sp
->file_out
;
121 unsigned int flags
= sp
->flags
& ~SPLICE_F_FD_IN_FIXED
;
122 loff_t
*poff_in
, *poff_out
;
126 WARN_ON_ONCE(issue_flags
& IO_URING_F_NONBLOCK
);
128 in
= io_splice_get_file(req
, issue_flags
);
134 poff_in
= (sp
->off_in
== -1) ? NULL
: &sp
->off_in
;
135 poff_out
= (sp
->off_out
== -1) ? NULL
: &sp
->off_out
;
138 ret
= do_splice(in
, poff_in
, out
, poff_out
, sp
->len
, flags
);
140 if (!(sp
->flags
& SPLICE_F_FD_IN_FIXED
))
145 io_req_set_res(req
, ret
, 0);