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 | 255 | IORING_OP_FUTEX_WAKE, |
| 256 | 256 | IORING_OP_FUTEX_WAITV, |
| 257 | 257 | IORING_OP_FIXED_FD_INSTALL, |
| 258 | + IORING_OP_FTRUNCATE, | |
| 258 | 259 | |
| 259 | 260 | /* this goes last, obviously */ |
| 260 | 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 | 8 | statx.o net.o msg_ring.o timeout.o \ |
| 9 | 9 | sqpoll.o fdinfo.o tctx.o poll.o \ |
| 10 | 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 | 12 | obj-$(CONFIG_IO_WQ) += io-wq.o |
| 13 | 13 | obj-$(CONFIG_FUTEX) += futex.o |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include "rw.h" |
| 36 | 36 | #include "waitid.h" |
| 37 | 37 | #include "futex.h" |
| 38 | +#include "truncate.h" | |
| 38 | 39 | |
| 39 | 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 | 475 | .prep = io_install_fixed_fd_prep, |
| 475 | 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 | 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 | 719 | [IORING_OP_FIXED_FD_INSTALL] = { |
| 713 | 720 | .name = "FIXED_FD_INSTALL", |
| 714 | 721 | }, |
| 722 | + [IORING_OP_FTRUNCATE] = { | |
| 723 | + .name = "FTRUNCATE", | |
| 724 | + }, | |
| 715 | 725 | }; |
| 716 | 726 | |
| 717 | 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); | |