Recent changes (master)

Jens Axboe <[email protected]> Mon, 12 Jan 2026 06:00:01 -0700
Newsgroups org.kernel.vger.fio
Message-ID <[email protected]>
The following changes since commit 6ff32768ff322a269f87cd515ecfb218400f22bf:

  Add option to specify ramp period by amount of IO (2026-01-07 14:01:53 -0500)

are available in the Git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to adeceb86edb28070cbae79dd38b5ec7354271063:

  Merge branch 'sync-fileop' of https://github.com/struschev/fio (2026-01-11 13:05:54 -0700)

----------------------------------------------------------------
Jens Axboe (3):
      t/io_uring: enable setting an opcode and register opcode filter
      Merge branch 'patch-1' of https://github.com/CookiePLMonster/fio
      Merge branch 'sync-fileop' of https://github.com/struschev/fio

Sergey Truschev (1):
      fio: add sync capability for file operations

Silent (1):
      windows: fix Y2038 bug caused by 32 bit truncation

 engines/falloc.c         | 20 +++++++++++-------
 engines/fileoperations.c |  2 ++
 engines/ftruncate.c      | 11 +++++-----
 os/windows/posix.c       |  2 +-
 t/io_uring.c             | 54 ++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 73 insertions(+), 16 deletions(-)

---

Diff of recent changes:

diff --git a/engines/falloc.c b/engines/falloc.c
index 290b980f..5bd5aa54 100644
--- a/engines/falloc.c
+++ b/engines/falloc.c
@@ -76,14 +76,18 @@ static enum fio_q_status fio_fallocate_queue(struct thread_data *td,
 
 	fio_ro_check(td, io_u);
 
-	if (io_u->ddir == DDIR_READ)
-		flags = FALLOC_FL_KEEP_SIZE;
-	else if (io_u->ddir == DDIR_WRITE)
-		flags = 0;
-	else if (io_u->ddir == DDIR_TRIM)
-		flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
-
-	ret = fallocate(f->fd, flags, io_u->offset, io_u->xfer_buflen);
+	if (io_u->ddir != DDIR_SYNC) {
+		if (io_u->ddir == DDIR_READ)
+			flags = FALLOC_FL_KEEP_SIZE;
+		else if (io_u->ddir == DDIR_WRITE)
+			flags = 0;
+		else if (io_u->ddir == DDIR_TRIM)
+			flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+
+		ret = fallocate(f->fd, flags, io_u->offset, io_u->xfer_buflen);
+	} else {
+		ret = do_io_u_sync(td, io_u);
+	}
 
 	if (ret)
 		io_u->error = errno;
diff --git a/engines/fileoperations.c b/engines/fileoperations.c
index e5303359..ce3e7c39 100644
--- a/engines/fileoperations.c
+++ b/engines/fileoperations.c
@@ -264,6 +264,8 @@ static int invalidate_do_nothing(struct thread_data *td, struct fio_file *f)
 
 static enum fio_q_status queue_io(struct thread_data *td, struct io_u *io_u)
 {
+	if (io_u->ddir == DDIR_SYNC && do_io_u_sync(td, io_u))
+		io_u->error = errno;
 	return FIO_Q_COMPLETED;
 }
 
diff --git a/engines/ftruncate.c b/engines/ftruncate.c
index d1757b79..70211e07 100644
--- a/engines/ftruncate.c
+++ b/engines/ftruncate.c
@@ -15,16 +15,17 @@ static enum fio_q_status fio_ftruncate_queue(struct thread_data *td,
 					     struct io_u *io_u)
 {
 	struct fio_file *f = io_u->file;
-	int ret;
+	int ret = 0;
 
 	fio_ro_check(td, io_u);
 
-	if (io_u->ddir != DDIR_WRITE) {
+	if (io_u->ddir == DDIR_WRITE)
+		ret = ftruncate(f->fd, io_u->offset);
+	else if (io_u->ddir == DDIR_SYNC)
+		ret = do_io_u_sync(td, io_u);
+	else
 		io_u->error = EINVAL;
-		return FIO_Q_COMPLETED;
-	}
 
-	ret = ftruncate(f->fd, io_u->offset);
 	if (ret)
 		io_u->error = errno;
 
diff --git a/os/windows/posix.c b/os/windows/posix.c
index 4c692a1e..ca3ee389 100644
--- a/os/windows/posix.c
+++ b/os/windows/posix.c
@@ -297,7 +297,7 @@ void Time_tToSystemTime(time_t dosTime, SYSTEMTIME *systemTime)
 	LONGLONG jan1970;
 	SYSTEMTIME tempSystemTime;
 
-	jan1970 = Int32x32To64(dosTime, 10000000) + 116444736000000000;
+	jan1970 = (dosTime * 10000000LL) + 116444736000000000LL;
 	utcFT.dwLowDateTime = (DWORD)jan1970;
 	utcFT.dwHighDateTime = jan1970 >> 32;
 
diff --git a/t/io_uring.c b/t/io_uring.c
index 9da5cc9e..0a04af4e 100644
--- a/t/io_uring.c
+++ b/t/io_uring.c
@@ -148,6 +148,7 @@ static int use_sync = 0;	/* use preadv2 */
 static int numa_placement = 0;	/* set to node of device */
 static int vectored = 0;	/* use vectored IO */
 static int pt = 0;		/* passthrough I/O or not */
+static int restriction = 0;	/* for testing restriction filter */
 
 static unsigned long tsc_rate;
 
@@ -883,6 +884,39 @@ static int setup_aio(struct submitter *s)
 #endif
 }
 
+static int io_uring_register_restrictions(struct submitter *s)
+{
+	struct io_uring_restriction res[8] = { };
+	int ret;
+
+	res[0].opcode = IORING_RESTRICTION_SQE_OP;
+	res[0].sqe_op = IORING_OP_NOP;
+	res[1].opcode = IORING_RESTRICTION_SQE_OP;
+	res[1].sqe_op = IORING_OP_READ;
+	res[2].opcode = IORING_RESTRICTION_SQE_OP;
+	res[2].sqe_op = IORING_OP_READV;
+	res[3].opcode = IORING_RESTRICTION_SQE_OP;
+	res[3].sqe_op = IORING_OP_READ_FIXED;
+
+	res[4].opcode = IORING_RESTRICTION_REGISTER_OP;
+	res[4].sqe_op = IORING_REGISTER_BUFFERS;
+	res[5].opcode = IORING_RESTRICTION_REGISTER_OP;
+	res[5].sqe_op = IORING_REGISTER_ENABLE_RINGS;
+	res[6].opcode = IORING_RESTRICTION_REGISTER_OP;
+	res[6].sqe_op = IORING_REGISTER_RING_FDS;
+	res[7].opcode = IORING_RESTRICTION_REGISTER_OP;
+	res[7].sqe_op = IORING_REGISTER_FILES;
+
+	ret = syscall(__NR_io_uring_register, s->ring_fd,
+			IORING_REGISTER_RESTRICTIONS, res, 8);
+	if (ret) {
+		fprintf(stderr, "IORING_REGISTER_RESTRICTIONS: %d\n", ret);
+		return ret;
+	}
+
+	return syscall(__NR_io_uring_register, s->ring_fd, IORING_REGISTER_ENABLE_RINGS, NULL, 0);
+}
+
 static int setup_ring(struct submitter *s)
 {
 	struct io_sq_ring *sring = &s->sq_ring;
@@ -907,6 +941,8 @@ static int setup_ring(struct submitter *s)
 		p.flags |= IORING_SETUP_SQE128;
 		p.flags |= IORING_SETUP_CQE32;
 	}
+	if (restriction)
+		p.flags |= IORING_SETUP_R_DISABLED;
 
 	fd = io_uring_setup(depth, &p);
 	if (fd < 0) {
@@ -915,6 +951,15 @@ static int setup_ring(struct submitter *s)
 	}
 	s->ring_fd = s->enter_ring_fd = fd;
 
+	if (restriction) {
+		/* enables rings too */
+		ret = io_uring_register_restrictions(s);
+		if (ret) {
+			fprintf(stderr, "Failed to set restrictions\n");
+			return ret;
+		}
+	}
+
 	if (fixedbufs) {
 		struct rlimit rlim;
 
@@ -1510,11 +1555,13 @@ static void usage(char *argv, int status)
 		" -X <bool> : Use registered ring %d\n"
 		" -P <bool> : Automatically place on device home node %d\n"
 		" -V <bool> : Vectored IO, default %d\n"
+		" -e <bool> : Set restriction filter on opcodes %d\n"
 		" -u <bool> : Use nvme-passthrough I/O, default %d\n",
 		argv, DEPTH, BATCH_SUBMIT, BATCH_COMPLETE, BS, polled,
 		fixedbufs, register_files, nthreads, !buffered, do_nop,
 		stats, runtime == 0 ? "unlimited" : runtime_str, random_io, aio,
-		use_sync, register_ring, numa_placement, vectored, pt);
+		use_sync, register_ring, numa_placement, vectored, restriction,
+		pt);
 	exit(status);
 }
 
@@ -1573,7 +1620,7 @@ int main(int argc, char *argv[])
 	if (!do_nop && argc < 2)
 		usage(argv[0], 1);
 
-	while ((opt = getopt(argc, argv, "d:s:c:b:p:B:F:n:N:O:t:T:a:r:D:R:X:S:P:V:u:h?")) != -1) {
+	while ((opt = getopt(argc, argv, "e:d:s:c:b:p:B:F:n:N:O:t:T:a:r:D:R:X:S:P:V:u:h?")) != -1) {
 		switch (opt) {
 		case 'a':
 			aio = !!atoi(optarg);
@@ -1657,6 +1704,9 @@ int main(int argc, char *argv[])
 		case 'u':
 			pt = !!atoi(optarg);
 			break;
+		case 'e':
+			restriction = !!atoi(optarg);
+			break;
 		case 'h':
 		case '?':
 		default: