diff mbox series

[2/2] io_uring: add support for ftruncate

Message ID 20240122193732.23217-2-tony.solomonik@gmail.com (mailing list archive)
State New
Headers show
Series [1/2] io_uring: add support for truncate | expand

Commit Message

Tony Solomonik Jan. 22, 2024, 7:37 p.m. UTC
Like truncate, ftruncate should also be supported in io_uring.
---
 include/uapi/linux/io_uring.h |  1 +
 io_uring/opdef.c              |  7 +++++++
 io_uring/truncate.c           | 37 +++++++++++++++++++++++++++++++++++
 io_uring/truncate.h           |  3 +++
 4 files changed, 48 insertions(+)

Comments

Jens Axboe Jan. 22, 2024, 8:12 p.m. UTC | #1
> +int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags)
> +{
> +	struct io_ftrunc *ft = io_kiocb_to_cmd(req, struct io_ftrunc);
> +	int ret;
> +
> +	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
> +
> +	ret = do_sys_ftruncate(ft->dfd, ft->len, 1);

This needs a __do_ftruncate() or something helper that takes a struct
file, that should be done as a prep patch. Then do_sys_ftruncate() can
call that helper as well, once it's done the fget.

With that, you also then remove the restriction you currently have that
it can't work on fixed files, there's no reason for that restriction to
be there.

Same comments on len vs offset, and the CLEANUP part. Both need to get
done here as well.
diff mbox series

Patch

diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 513f31ee8ce9..8ebaf667c07d 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -254,6 +254,7 @@  enum io_uring_op {
 	IORING_OP_FUTEX_WAKE,
 	IORING_OP_FUTEX_WAITV,
 	IORING_OP_TRUNCATE,
+	IORING_OP_FTRUNCATE,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
diff --git a/io_uring/opdef.c b/io_uring/opdef.c
index 60827099e244..88054f3df83c 100644
--- a/io_uring/opdef.c
+++ b/io_uring/opdef.c
@@ -474,6 +474,10 @@  const struct io_issue_def io_issue_defs[] = {
 		.prep			= io_truncate_prep,
 		.issue			= io_truncate,
 	},
+	[IORING_OP_FTRUNCATE] = {
+		.prep			= io_ftruncate_prep,
+		.issue			= io_ftruncate,
+	},
 };
 
 const struct io_cold_def io_cold_defs[] = {
@@ -712,6 +716,9 @@  const struct io_cold_def io_cold_defs[] = {
 	[IORING_OP_TRUNCATE] = {
 		.name			= "TRUNCATE",
 	},
+	[IORING_OP_FTRUNCATE] = {
+		.name			= "FTRUNCATE",
+	},
 };
 
 const char *io_uring_get_opcode(u8 opcode)
diff --git a/io_uring/truncate.c b/io_uring/truncate.c
index 82648b2fbc7e..e31d28a478d2 100644
--- a/io_uring/truncate.c
+++ b/io_uring/truncate.c
@@ -21,6 +21,12 @@  struct io_trunc {
 	loff_t				len;
 };
 
+struct io_ftrunc {
+	struct file			*file;
+	int				dfd;
+	loff_t				len;
+};
+
 int io_truncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
 	struct io_trunc *tr = io_kiocb_to_cmd(req, struct io_trunc);
@@ -51,3 +57,34 @@  int io_truncate(struct io_kiocb *req, unsigned int issue_flags)
 	io_req_set_res(req, ret, 0);
 	return IOU_OK;
 }
+
+int io_ftruncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+	struct io_ftrunc *ft = io_kiocb_to_cmd(req, struct io_ftrunc);
+
+	if (sqe->off || sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
+		return -EINVAL;
+	if (unlikely(req->flags & REQ_F_FIXED_FILE))
+		return -EBADF;
+
+	ft->dfd = READ_ONCE(sqe->fd);
+	ft->len = READ_ONCE(sqe->len);
+
+	req->flags |= REQ_F_NEED_CLEANUP;
+	req->flags |= REQ_F_FORCE_ASYNC;
+	return 0;
+}
+
+int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags)
+{
+	struct io_ftrunc *ft = io_kiocb_to_cmd(req, struct io_ftrunc);
+	int ret;
+
+	WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
+
+	ret = do_sys_ftruncate(ft->dfd, ft->len, 1);
+
+	req->flags &= ~REQ_F_NEED_CLEANUP;
+	io_req_set_res(req, ret, 0);
+	return IOU_OK;
+}
diff --git a/io_uring/truncate.h b/io_uring/truncate.h
index ab17cb9acc90..a9fc20b5f926 100644
--- a/io_uring/truncate.h
+++ b/io_uring/truncate.h
@@ -2,3 +2,6 @@ 
 
 int io_truncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 int io_truncate(struct io_kiocb *req, unsigned int issue_flags);
+
+int io_ftruncate_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_ftruncate(struct io_kiocb *req, unsigned int issue_flags);