All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v6 1/2] io_uring: Add test for READV and WRITEV operations
@ 2026-04-16 12:16 Sachin Sant
  2026-04-16 12:16 ` [LTP] [PATCH 2/2] io_uring: remove unused io_uring_init_buffer_pattern() Sachin Sant
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Sachin Sant @ 2026-04-16 12:16 UTC (permalink / raw)
  To: ltp

Add a test to validate vectored read and write operations using io_uring.

1. IORING_OP_WRITEV - Writing data using multiple buffers (scatter)
2. IORING_OP_READV - Reading data into multiple buffers (gather)
3. Data integrity verification across multiple iovecs
4. Edge cases with different iovec configurations including zero
   buffer length

Additionally merge io_uring_init_buffer_pattern() into unified
init_iovec_buffers() function that supports both rotating and
simple character patterns

Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
---
V5 changes:
- Add clear_iovec_buffers() at the top of run()
- Link to v4 https://lore.kernel.org/ltp/20260416062302.15804-1-sachinp@linux.ibm.com/T/

V4 changes:
- Updated commit message to remove references to non-existent function
- Removed extra blank line before test_writev_readv()
- Link to v3 https://lore.kernel.org/ltp/20260416042531.81093-1-sachinp@linux.ibm.com/T/

V3 changes (2/3 io_uring04 only):
- 1/3 and 3/3 from the patch series already merged.
- Merged prepare_read_buffers() and clear_iovec_buffers() into
single clear_iovec_buffers() function
- Merged io_uring_init_buffer_pattern() into unified
init_iovec_buffers() function that supports both rotating and
simple character patterns
- Removed io_uring_init_buffer_pattern() from io_uring_common.h as it's
only used in io_uring04.c
- Link to V2: https://lore.kernel.org/ltp/b4653e3f-ac9b-4a24-8d3f-51677c488e8c@linux.ibm.com/T/

V2 changes:
- Use guarded buffer(including iovec) allocation
- Move setup/cleanup code from run to appropriate path
- Add a function to map the OP to the enum name
- Define and use generic cleanup functions
- Add a buffer size 0 in the middle of the iovec
- Simplify setup_io_uring_test to use common code.
- Link to V1: https://lore.kernel.org/ltp/20260320124742.75946-1-sachinp@linux.ibm.com/T/#t

Changes after RFC patch series:
- Addressed review comments
- Refactored io_uring01 test to use common code
- Removed git tags
- Link to RFC: https://lore.kernel.org/ltp/20260318110328.52031-1-sachinp@linux.ibm.com/T/#t

---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/io_uring/.gitignore |   1 +
 .../kernel/syscalls/io_uring/io_uring04.c     | 223 ++++++++++++++++++
 3 files changed, 225 insertions(+)
 create mode 100644 testcases/kernel/syscalls/io_uring/io_uring04.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 5025b259f..aa7a91d97 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1901,6 +1901,7 @@ membarrier01 membarrier01
 io_uring01 io_uring01
 io_uring02 io_uring02
 io_uring03 io_uring03
+io_uring04 io_uring04
 
 # Tests below may cause kernel memory leak
 perf_event_open03 perf_event_open03
diff --git a/testcases/kernel/syscalls/io_uring/.gitignore b/testcases/kernel/syscalls/io_uring/.gitignore
index 9382ae413..36cd24662 100644
--- a/testcases/kernel/syscalls/io_uring/.gitignore
+++ b/testcases/kernel/syscalls/io_uring/.gitignore
@@ -1,3 +1,4 @@
 /io_uring01
 /io_uring02
 /io_uring03
+/io_uring04
diff --git a/testcases/kernel/syscalls/io_uring/io_uring04.c b/testcases/kernel/syscalls/io_uring/io_uring04.c
new file mode 100644
index 000000000..6b6bb711d
--- /dev/null
+++ b/testcases/kernel/syscalls/io_uring/io_uring04.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 IBM
+ * Author: Sachin Sant <sachinp@linux.ibm.com>
+ */
+/*\
+ * Test IORING_OP_READV and IORING_OP_WRITEV operations.
+ *
+ * This test validates vectored read and write operations using io_uring.
+ * It tests:
+ * 1. IORING_OP_WRITEV - Writing data using multiple buffers (scatter)
+ * 2. IORING_OP_READV - Reading data into multiple buffers (gather)
+ * 3. Data integrity verification across multiple iovecs
+ * 4. Edge cases with different iovec configurations
+ */
+
+#include "io_uring_common.h"
+
+#define TEST_FILE "io_uring_test_file"
+#define QUEUE_DEPTH 2
+#define NUM_VECS 4
+#define VEC_SIZE 1024
+#define VAR_BUF1_SIZE 512
+#define VAR_BUF2_SIZE 1024
+#define VAR_BUF3_SIZE 256
+
+static struct iovec *write_iovs, *read_iovs;
+static struct iovec *var_write_iovs, *var_read_iovs;
+static struct io_uring_submit s;
+static sigset_t sig;
+
+/*
+ * Initialize iovec buffers with pattern
+ * @iovs: array of iovec structures
+ * @nvecs: number of iovecs
+ * @base_char: base character for pattern
+ * @use_rotating: if true, use rotating pattern; if false, use simple repeat
+ */
+static void init_iovec_buffers(struct iovec *iovs, int nvecs,
+				char base_char, int use_rotating)
+{
+	int i;
+	size_t j;
+	char *buf;
+
+	for (i = 0; i < nvecs; i++) {
+		if (iovs[i].iov_len == 0)
+			continue;
+
+		buf = (char *)iovs[i].iov_base;
+		if (use_rotating) {
+			/* Each vector has a different rotating pattern */
+			for (j = 0; j < iovs[i].iov_len; j++)
+				buf[j] = base_char + i + (j % 26);
+		} else {
+			for (j = 0; j < iovs[i].iov_len; j++)
+				buf[j] = base_char + i;
+		}
+	}
+}
+
+static void clear_iovec_buffers(struct iovec *iovs, int nvecs)
+{
+	int i;
+
+	for (i = 0; i < nvecs; i++)
+		memset(iovs[i].iov_base, 0, iovs[i].iov_len);
+}
+
+static void verify_iovec_data(struct iovec *write_iovs, struct iovec *read_iovs,
+			      int nvecs, const char *test_name)
+{
+	int i;
+	size_t j;
+
+	for (i = 0; i < nvecs; i++) {
+		if (write_iovs[i].iov_len != read_iovs[i].iov_len) {
+			tst_res(TFAIL, "%s: iovec %d length mismatch: write=%zu read=%zu",
+				test_name, i, write_iovs[i].iov_len, read_iovs[i].iov_len);
+			return;
+		}
+
+		if (memcmp(write_iovs[i].iov_base, read_iovs[i].iov_base,
+			   write_iovs[i].iov_len) != 0) {
+			tst_res(TFAIL, "%s: data mismatch in vector %d", test_name, i);
+			for (j = 0; j < write_iovs[i].iov_len && j < 64; j++) {
+				char *wbuf = (char *)write_iovs[i].iov_base;
+				char *rbuf = (char *)read_iovs[i].iov_base;
+				if (wbuf[j] != rbuf[j]) {
+					tst_res(TINFO, "Vector %d: first mismatch at "
+						"offset %zu: wrote 0x%02x, read 0x%02x",
+						i, j, wbuf[j], rbuf[j]);
+					break;
+				}
+			}
+			return;
+		}
+	}
+
+	tst_res(TPASS, "%s: data integrity verified across %d vectors",
+		test_name, nvecs);
+}
+
+static void test_writev_readv(void)
+{
+	int fd;
+	int total_size = NUM_VECS * VEC_SIZE;
+
+	tst_res(TINFO, "Testing IORING_OP_WRITEV and IORING_OP_READV");
+
+	fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
+
+	tst_res(TINFO, "Writing %d bytes using %d vectors", total_size, NUM_VECS);
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_WRITEV, write_iovs, NUM_VECS,
+			      0, total_size, &sig);
+
+	SAFE_FSYNC(fd);
+
+	tst_res(TINFO, "Reading %d bytes using %d vectors", total_size, NUM_VECS);
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_READV, read_iovs, NUM_VECS,
+			      0, total_size, &sig);
+
+	verify_iovec_data(write_iovs, read_iovs, NUM_VECS, "Basic vectored I/O");
+
+	SAFE_CLOSE(fd);
+}
+
+static void test_partial_vectors(void)
+{
+	int fd;
+	int half_size = 2 * VEC_SIZE;
+
+	tst_res(TINFO, "Testing partial vector operations");
+
+	fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
+
+	/* Write first half using first 2 vectors at offset 0 */
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_WRITEV, write_iovs, 2, 0,
+			      half_size, &sig);
+
+	/* Write second half using next 2 vectors at offset half_size */
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_WRITEV, &write_iovs[2], 2,
+			      half_size, half_size, &sig);
+
+	SAFE_FSYNC(fd);
+
+	/* Read back entire file using all 4 vectors */
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_READV, read_iovs, NUM_VECS, 0,
+			      NUM_VECS * VEC_SIZE, &sig);
+
+	verify_iovec_data(write_iovs, read_iovs, NUM_VECS, "Partial vector I/O");
+
+	SAFE_CLOSE(fd);
+}
+
+static void test_varying_sizes(void)
+{
+	int fd;
+	int expected_size = VAR_BUF1_SIZE + VAR_BUF2_SIZE + VAR_BUF3_SIZE;
+
+	tst_res(TINFO, "Testing vectors with varying sizes including zero-length buffer");
+
+	init_iovec_buffers(var_write_iovs, 4, 'X', 0);
+
+	clear_iovec_buffers(var_read_iovs, 4);
+
+	fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
+
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_WRITEV, var_write_iovs, 4, 0,
+			      expected_size, &sig);
+
+	SAFE_FSYNC(fd);
+
+	io_uring_do_vec_io_op(&s, fd, IORING_OP_READV, var_read_iovs, 4, 0,
+			      expected_size, &sig);
+
+	verify_iovec_data(var_write_iovs, var_read_iovs, 4, "Varying size vector I/O with zero-length buffer");
+
+	SAFE_CLOSE(fd);
+}
+
+static void run(void)
+{
+	clear_iovec_buffers(read_iovs, NUM_VECS);
+
+	test_writev_readv();
+	test_partial_vectors();
+	test_varying_sizes();
+}
+
+static void setup(void)
+{
+	io_uring_setup_supported_by_kernel();
+	sigemptyset(&sig);
+	memset(&s, 0, sizeof(s));
+	io_uring_setup_queue(&s, QUEUE_DEPTH, 0);
+	init_iovec_buffers(write_iovs, NUM_VECS, 'A', 1);
+	clear_iovec_buffers(read_iovs, NUM_VECS);
+}
+
+static void cleanup(void)
+{
+	io_uring_cleanup_queue(&s, QUEUE_DEPTH);
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.bufs = (struct tst_buffers []) {
+		{&write_iovs, .iov_sizes = (int[]){VEC_SIZE, VEC_SIZE, VEC_SIZE, VEC_SIZE, -1}},
+		{&read_iovs, .iov_sizes = (int[]){VEC_SIZE, VEC_SIZE, VEC_SIZE, VEC_SIZE, -1}},
+		{&var_write_iovs, .iov_sizes = (int[]){VAR_BUF1_SIZE, 0, VAR_BUF2_SIZE, VAR_BUF3_SIZE, -1}},
+		{&var_read_iovs, .iov_sizes = (int[]){VAR_BUF1_SIZE, 0, VAR_BUF2_SIZE, VAR_BUF3_SIZE, -1}},
+		{}
+	},
+	.save_restore = (const struct tst_path_val[]) {
+		{"/proc/sys/kernel/io_uring_disabled", "0",
+			TST_SR_SKIP_MISSING | TST_SR_TCONF_RO},
+		{}
+	}
+};
-- 
2.39.1


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-05-06 12:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-16 12:16 [LTP] [PATCH v6 1/2] io_uring: Add test for READV and WRITEV operations Sachin Sant
2026-04-16 12:16 ` [LTP] [PATCH 2/2] io_uring: remove unused io_uring_init_buffer_pattern() Sachin Sant
2026-04-16 13:47 ` [LTP] io_uring: Add test for READV and WRITEV operations linuxtestproject.agent
2026-05-06 11:45 ` [LTP] [PATCH v6 1/2] " Andrea Cervesato via ltp
2026-05-06 12:11   ` Sachin Sant
2026-05-06 12:27     ` Andrea Cervesato via ltp

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.