Recent changes (master)

Jens Axboe <[email protected]> Wed, 13 May 2026 06:00:01 -0600
Newsgroups org.kernel.vger.fio
Message-ID <[email protected]>
The following changes since commit 72156dca3d41df7d05ea4e5a4e59623c2d393a92:

  Merge branch 'codex/cgroup-path-overflows' of https://github.com/linuxholic/fio (2026-04-30 06:53:46 -0600)

are available in the Git repository at:

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

for you to fetch changes up to 3ea531dfc54aaccb6a5846f37e6cfefedd7ff60e:

  Merge branch 't_io_uring_htlb' of https://github.com/ming1/fio (2026-05-12 10:21:09 -0600)

----------------------------------------------------------------
Jens Axboe (1):
      Merge branch 't_io_uring_htlb' of https://github.com/ming1/fio

Ming Lei (1):
      t/io_uring: add --hugetlb option for hugetlbfs IO buffers

 t/io_uring.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 68 insertions(+), 2 deletions(-)

---

Diff of recent changes:

diff --git a/t/io_uring.c b/t/io_uring.c
index 0a04af4e..64d30d95 100644
--- a/t/io_uring.c
+++ b/t/io_uring.c
@@ -114,12 +114,20 @@ struct submitter {
 	int per_file_depth;
 	const char *filename;
 
+	void *htlb_buf;		/* pre-assigned hugetlb buffer */
+
 	struct file files[MAX_FDS];
 	unsigned nr_files;
 	unsigned cur_file;
 	struct iovec iovecs[];
 };
 
+struct htlb_alloc {
+	char *path;		/* hugetlbfs file path */
+	void *base;		/* mmap base */
+	size_t size;		/* total mmap size */
+};
+
 static struct submitter *submitter;
 static volatile int finish;
 static int stats_running;
@@ -149,6 +157,7 @@ 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 struct htlb_alloc htlb;
 
 static unsigned long tsc_rate;
 
@@ -1034,6 +1043,11 @@ static void *allocate_mem(struct submitter *s, int size)
 {
 	void *buf;
 
+	if (s->htlb_buf) {
+		buf = s->htlb_buf;
+		s->htlb_buf = (char *)buf + size;
+		return buf;
+	}
 #ifdef CONFIG_LIBNUMA
 	if (s->numa_node != -1)
 		return numa_alloc_onnode(size, s->numa_node);
@@ -1531,6 +1545,51 @@ static void arm_sig_int(void)
 #endif
 }
 
+static int setup_hugetlb(void)
+{
+	size_t needed, per_thread;
+	struct stat st;
+	int fd, j;
+
+	fd = open(htlb.path, O_RDWR);
+	if (fd < 0) {
+		perror("open hugetlb file");
+		return -1;
+	}
+
+	if (fstat(fd, &st) < 0 || st.st_size <= 0) {
+		fprintf(stderr, "hugetlb file %s: invalid size\n", htlb.path);
+		close(fd);
+		return -1;
+	}
+
+	htlb.size = st.st_size;
+	needed = (size_t)nthreads * bs * roundup_pow2(depth);
+	if (htlb.size < needed) {
+		fprintf(stderr, "hugetlb file too small: %zu < %zu "
+			"(%d threads × %d bs × %d depth)\n",
+			htlb.size, needed, nthreads, bs, roundup_pow2(depth));
+		close(fd);
+		return -1;
+	}
+
+	htlb.base = mmap(NULL, htlb.size, PROT_READ | PROT_WRITE,
+			 MAP_SHARED | MAP_POPULATE, fd, 0);
+	close(fd);
+	if (htlb.base == MAP_FAILED) {
+		perror("mmap hugetlb file");
+		htlb.base = NULL;
+		return -1;
+	}
+
+	per_thread = bs * roundup_pow2(depth);
+	for (j = 0; j < nthreads; j++)
+		get_submitter(j)->htlb_buf = (char *)htlb.base + j * per_thread;
+
+	printf("Using hugetlb file %s, size %zu\n", htlb.path, htlb.size);
+	return 0;
+}
+
 static void usage(char *argv, int status)
 {
 	char runtime_str[16];
@@ -1556,7 +1615,8 @@ static void usage(char *argv, int status)
 		" -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",
+		" -u <bool> : Use nvme-passthrough I/O, default %d\n"
+		" -H <path> : Use hugetlbfs file for IO buffers\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,
@@ -1620,7 +1680,7 @@ int main(int argc, char *argv[])
 	if (!do_nop && argc < 2)
 		usage(argv[0], 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) {
+	while ((opt = getopt(argc, argv, "e:d:s:c:b:p:B:F:H:n:N:O:t:T:a:r:D:R:X:S:P:V:u:h?")) != -1) {
 		switch (opt) {
 		case 'a':
 			aio = !!atoi(optarg);
@@ -1707,6 +1767,9 @@ int main(int argc, char *argv[])
 		case 'e':
 			restriction = !!atoi(optarg);
 			break;
+		case 'H':
+			htlb.path = strdup(optarg);
+			break;
 		case 'h':
 		case '?':
 		default:
@@ -1802,6 +1865,9 @@ int main(int argc, char *argv[])
 	if (t_io_uring_page_size < 0)
 		t_io_uring_page_size = 4096;
 
+	if (htlb.path && setup_hugetlb())
+		return 1;
+
 	for (j = 0; j < nthreads; j++) {
 		s = get_submitter(j);
 		if (use_sync)