Thread (17 messages) flat view 17 messages, 5 authors, 21h ago

Re: [net-next,v6,5/6] selftests: net: add multithread server support to iou-zcrx

From: Bobby Eshleman <hidden>
Date: 2026-09-09 16:17:04
Also in: io-uring, linux-kselftest, lkml

On Wed, Sep 02, 2026 at 11:38:17PM +0000, netdev-bot+sashiko@kernel.org wrote:
Thank you for your contribution! Sashiko AI review found 6 potential
issue(s) to consider:
[...]
quoted
@@ -356,29 +444,68 @@ static void run_server(void)
 	if (ret < 0)
 		error(1, 0, "bind()");
 
-	flags |= IORING_SETUP_COOP_TASKRUN;
-	flags |= IORING_SETUP_SINGLE_ISSUER;
-	flags |= IORING_SETUP_DEFER_TASKRUN;
-	flags |= IORING_SETUP_SUBMIT_ALL;
-	flags |= IORING_SETUP_CQE32;
+	pthread_barrier_init(&setup_done, NULL, cfg_num_threads + 1);
+	pthread_barrier_init(&dispatch_done, NULL, cfg_num_threads + 1);
+
+	for (i = 0; i < cfg_num_threads; i++) {
+		ctxs[i].queue_id = cfg_queue_id + i;
+		ctxs[i].setup_done = &setup_done;
+		ctxs[i].dispatch_done = &dispatch_done;
+	}
 
-	io_uring_queue_init(512, &ctx.ring, flags);
+	for (i = 0; i < cfg_num_threads; i++) {
+		ret = pthread_create(&threads[i], NULL,
+				     server_worker, &ctxs[i]);
+		if (ret)
+			error(1, ret, "pthread_create()");
+	}
 
-	setup_zcrx(&ctx);
 	if (cfg_dry_run)
-		return;
+		goto join;
 
 	if (listen(fd, 1024) < 0)
 		error(1, 0, "listen()");
 
-	add_accept(&ctx, fd);
+	pthread_barrier_wait(&setup_done);
[Severity: High]
Is the listen() intentionally moved before the workers have registered
their ifqs? The main thread creates the threads, calls listen(), and only
then waits on setup_done, while the workers reach that barrier after
io_uring_queue_init_params() plus setup_zcrx(), i.e. after
io_uring_register_ifq() has restarted the device RX queue.

Before the patch the sequence was serialized in one thread:

	io_uring_queue_init(512, &ctx.ring, flags);
	setup_zcrx(&ctx);
	...
	listen(fd, 1024);

so the port only became visible once the memory provider was installed.

Two existing tests depend on that ordering. wait_port_listen() in
net/lib/py/utils.py polls every 5 ms, so it can now return while
registration is still in flight:

iou-zcrx.py:test_zcrx_large_chunks() {
	wait_port_listen(cfg.port, proto="tcp")

	check_iou_rx_buf_len(cfg, rx_buf_len)
}

check_iou_rx_buf_len() raises "Expected 1 io-uring page pool, found 0",
and nk_qlease.py:test_destroy() does queue_get() plus
ksft_in("io-uring", queue_info) immediately after wait_port_listen() with
no sleep.

Beyond the harness races, data delivered into the queue before the
provider exists is serviced by the copy fallback rather than zero copy,
and the queue restart during registration can drop in-flight frames.

Would moving listen() below pthread_barrier_wait(&setup_done) restore the
previous guarantee?
Just a heads up that I tested this on BRCM and did find this listen()
ordering issue to cause genuine (but flaky) regression for
nk_qlease.test_destroy. Moving the listen() to after wait(setup_done)
indeed fixed it.

Best,
Bobby
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help