@@ -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,
@@ -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)
@@ -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;
+}
@@ -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);