Adds support for doing truncate through io_uring, eliminating the need for applications to roll their own thread pool or offload mechanism to be able to do non-blocking truncates.
Unified · Split
| @@ -255,6 +255,7 @@ enum io_uring_op { · 254 unmodified lines | |||
| 255 | IORING_OP_FUTEX_WAKE, | 255 | IORING_OP_FUTEX_WAKE, |
| 256 | IORING_OP_FUTEX_WAITV, | 256 | IORING_OP_FUTEX_WAITV, |
| 257 | IORING_OP_FIXED_FD_INSTALL, | 257 | IORING_OP_FIXED_FD_INSTALL, |
| 258 | IORING_OP_FTRUNCATE, | ||
| 258 | 259 | ||
| 259 | /* this goes last, obviously */ | 260 | /* this goes last, obviously */ |
| 260 | IORING_OP_LAST, | 261 | IORING_OP_LAST, |
| @@ -8,6 +8,6 @@ obj-$(CONFIG_IO_URING) += io_uring.o xattr.o nop.o fs.o splice.o \ · 7 unmodified lines | |||
| 8 | statx.o net.o msg_ring.o timeout.o \ | 8 | statx.o net.o msg_ring.o timeout.o \ |
| 9 | sqpoll.o fdinfo.o tctx.o poll.o \ | 9 | sqpoll.o fdinfo.o tctx.o poll.o \ |
| 10 | cancel.o kbuf.o rsrc.o rw.o opdef.o \ | 10 | cancel.o kbuf.o rsrc.o rw.o opdef.o \ |
| 11 | notif.o waitid.o register.o | 11 | notif.o waitid.o register.o truncate.o |
| 12 | obj-$(CONFIG_IO_WQ) += io-wq.o | 12 | obj-$(CONFIG_IO_WQ) += io-wq.o |
| 13 | obj-$(CONFIG_FUTEX) += futex.o | 13 | obj-$(CONFIG_FUTEX) += futex.o |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | |||
| 35 | #include "rw.h" | 35 | #include "rw.h" |
| 36 | #include "waitid.h" | 36 | #include "waitid.h" |
| 37 | #include "futex.h" | 37 | #include "futex.h" |
| 38 | #include "truncate.h" | ||
| 38 | 39 | ||
| 39 | static int io_no_issue(struct io_kiocb *req, unsigned int issue_flags) | 40 | static int io_no_issue(struct io_kiocb *req, unsigned int issue_flags) |
| 40 | { | 41 | { |
| @@ -474,6 +475,12 @@ const struct io_issue_def io_issue_defs[] = { · 433 unmodified lines | |||
| 474 | .prep = io_install_fixed_fd_prep, | 475 | .prep = io_install_fixed_fd_prep, |
| 475 | .issue = io_install_fixed_fd, | 476 | .issue = io_install_fixed_fd, |
| 476 | }, | 477 | }, |
| 478 | [IORING_OP_FTRUNCATE] = { | ||
| 479 | .needs_file = 1, | ||
| 480 | .hash_reg_file = 1, | ||
| 481 | .prep = io_ftruncate_prep, | ||
| 482 | .issue = io_ftruncate, | ||
| 483 | }, | ||
| 477 | }; | 484 | }; |
| 478 | 485 | ||
| 479 | const struct io_cold_def io_cold_defs[] = { | 486 | const struct io_cold_def io_cold_defs[] = { |
| @@ -712,6 +719,9 @@ const struct io_cold_def io_cold_defs[] = { · 232 unmodified lines | |||
| 712 | [IORING_OP_FIXED_FD_INSTALL] = { | 719 | [IORING_OP_FIXED_FD_INSTALL] = { |
| 713 | .name = "FIXED_FD_INSTALL", | 720 | .name = "FIXED_FD_INSTALL", |
| 714 | }, | 721 | }, |
| 722 | [IORING_OP_FTRUNCATE] = { | ||
| 723 | .name = "FTRUNCATE", | ||
| 724 | }, | ||
| 715 | }; | 725 | }; |
| 716 | 726 | ||
| 717 | const char *io_uring_get_opcode(u8 opcode) | 727 | const char *io_uring_get_opcode(u8 opcode) |
| @@ -0,0 +1,48 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | #include <linux/kernel.h> | ||
| 3 | #include <linux/errno.h> | ||
| 4 | #include <linux/fs.h> | ||
| 5 | #include <linux/file.h> | ||
| 6 | #include <linux/mm.h> | ||
| 7 | #include <linux/slab.h> | ||
| 8 | #include <linux/syscalls.h> | ||
| 9 | #include <linux/io_uring.h> | ||
| 10 | |||
| 11 | #include <uapi/linux/io_uring.h> | ||
| 12 | |||
| 13 | #include "../fs/internal.h" | ||
| 14 | |||
| 15 | #include "io_uring.h" | ||
| 16 | #include "truncate.h" | ||
| 17 | |||
| 18 | struct io_ftrunc { | ||
| 19 | struct file *file; | ||
| 20 | loff_t len; | ||
| 21 | }; | ||
| 22 | |||
| 23 | int io_ftruncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | ||
| 24 | { | ||
| 25 | struct io_ftrunc *ft = io_kiocb_to_cmd(req, struct io_ftrunc); | ||
| 26 | |||
| 27 | if (sqe->rw_flags || sqe->addr || sqe->len || sqe->buf_index || | ||
| 28 | sqe->splice_fd_in || sqe->addr3) | ||
| 29 | return -EINVAL; | ||
| 30 | |||
| 31 | ft->len = READ_ONCE(sqe->off); | ||
| 32 | |||
| 33 | req->flags |= REQ_F_FORCE_ASYNC; | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags) | ||
| 38 | { | ||
| 39 | struct io_ftrunc *ft = io_kiocb_to_cmd(req, struct io_ftrunc); | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); | ||
| 43 | |||
| 44 | ret = do_ftruncate(req->file, ft->len, 1); | ||
| 45 | |||
| 46 | io_req_set_res(req, ret, 0); | ||
| 47 | return IOU_OK; | ||
| 48 | } | ||
| @@ -0,0 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | int io_ftruncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); | ||
| 4 | int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags); | ||