All of lore.kernel.org
 help / color / mirror / Atom feed
From: Avinesh Kumar via ltp <ltp@lists.linux.it>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH v2] uevent02: Make wait_for_uevents() order-independent
Date: Fri, 28 Aug 2026 17:26:30 +0200	[thread overview]
Message-ID: <20260828152631.254653-1-avinesh.kumar@suse.com> (raw)
In-Reply-To: <20260825173613.8867-1-linuxtestproject.agent@gmail.com>

From: Avinesh Kumar <avinesh.kumar@suse.com>

Commit 8e63c9e6179a ("net: Defer netdev KOBJ_ADD uevent until the
device is published")[0] moved a network interface's "add" uevent to
after its queue kobjects are created, flipping the uevent order for
tun device creation from:

    add(net), add(rx queue), add(tx queue)
to:
    add(rx queue), add(tx queue), add(net)

wait_for_uevents() matches events strictly in array order, so on
kernels with the new order "add(net)" is still awaited after its queue
events have already been consumed off the socket, and uevent02 hangs
until it times out and fails.

The relative order of these uevents is a kernel implementation detail
the test shouldn't depend on. Track still-unmatched events in a
pending set and match incoming uevents against any of them regardless
of position.

wait_for_uevents() leaves fd open so it can be called more than once on
the same socket, keeping independent lifecycle phases ordered: uevent02
matches all add events before looking for the remove events.

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8e63c9e6179a

Signed-off-by: Avinesh Kumar <avinesh.kumar@suse.com>
---
 testcases/kernel/uevents/uevent.h   | 39 +++++++++++++++++++++++------
 testcases/kernel/uevents/uevent02.c | 28 +++++++++++++--------
 2 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/testcases/kernel/uevents/uevent.h b/testcases/kernel/uevents/uevent.h
index 1ad092d5ea39..f7e7c671e499 100644
--- a/testcases/kernel/uevents/uevent.h
+++ b/testcases/kernel/uevents/uevent.h
@@ -117,15 +117,34 @@ static inline int open_uevent_netlink(void)
 	return fd;
 }
 
+#define UEVENT_MAX_PENDING 16
+
 /*
  * Reads events from uevent netlink socket until all expected events passed in
- * the uevent array are matched.
+ * the uevent array are matched. Events do not have to arrive in the order
+ * they are listed in the uevents array, since the kernel is free to reorder
+ * unrelated uevents, e.g. commit 8e63c9e6179a ("net: Defer netdev KOBJ_ADD
+ * uevent until the device is published") changed the order in which a
+ * network interface and its queues announce themselves.
+ *
+ * Does not close fd; the caller owns the socket and can call this more
+ * than once on it to keep independent lifecycle phases ordered, e.g.
+ * matching all "add" events before looking for "remove" events.
  */
 static inline void wait_for_uevents(int fd, const struct uevent_desc *const uevents[])
 {
-	int i = 0;
+	const struct uevent_desc *pending[UEVENT_MAX_PENDING];
+	int i, cnt = 0, remaining;
+
+	while (uevents[cnt]) {
+		if (cnt >= UEVENT_MAX_PENDING)
+			tst_brk(TBROK, "Too many expected uevents, increase UEVENT_MAX_PENDING");
+		pending[cnt] = uevents[cnt];
+		cnt++;
+	}
+	remaining = cnt;
 
-	while (1) {
+	while (remaining) {
 		int len;
 		char buf[4096];
 
@@ -136,11 +155,15 @@ static inline void wait_for_uevents(int fd, const struct uevent_desc *const ueve
 
 		print_uevent(buf, len);
 
-		if (uevent_match(buf, len, uevents[i])) {
-			tst_res(TPASS, "Got expected UEVENT");
-			if (!uevents[++i]) {
-				close(fd);
-				return;
+		for (i = 0; i < cnt; i++) {
+			if (!pending[i])
+				continue;
+
+			if (uevent_match(buf, len, pending[i])) {
+				tst_res(TPASS, "Got expected UEVENT");
+				pending[i] = NULL;
+				remaining--;
+				break;
 			}
 		}
 	}
diff --git a/testcases/kernel/uevents/uevent02.c b/testcases/kernel/uevents/uevent02.c
index 1135f55a87db..26c0dbd10547 100644
--- a/testcases/kernel/uevents/uevent02.c
+++ b/testcases/kernel/uevents/uevent02.c
@@ -25,7 +25,8 @@
 #include "uevent.h"
 
 #define TUN_PATH "/dev/net/tun"
-#define MAX_UEVENTS 7
+#define MAX_ADD_UEVENTS 4
+#define MAX_REM_UEVENTS 4
 
 static struct uevent_desc add = {
 	.msg = "add@/devices/virtual/net/ltp-tun0",
@@ -88,7 +89,8 @@ static struct uevent_desc rem = {
 		"INTERFACE=ltp-tun0",
 	}
 };
-static const struct uevent_desc *uevents[MAX_UEVENTS];
+static const struct uevent_desc *add_uevents[MAX_ADD_UEVENTS];
+static const struct uevent_desc *rem_uevents[MAX_REM_UEVENTS];
 
 static void generate_tun_uevents(void)
 {
@@ -114,7 +116,9 @@ static void verify_uevent(void)
 	if (!pid) {
 		fd = open_uevent_netlink();
 		TST_CHECKPOINT_WAKE(0);
-		wait_for_uevents(fd, uevents);
+		wait_for_uevents(fd, add_uevents);
+		wait_for_uevents(fd, rem_uevents);
+		close(fd);
 		exit(0);
 	}
 
@@ -128,19 +132,21 @@ static void verify_uevent(void)
 static void setup(void)
 {
 	struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_RPS");
-	int i = 0;
+	int i = 0, j = 0;
 
 	tst_kconfig_read(&kconfig, 1);
 
-	uevents[i++] = &add;
+	add_uevents[i++] = &add;
 	if (kconfig.choice == 'y')
-		uevents[i++] = &add_rx;
-	uevents[i++] = &add_tx;
+		add_uevents[i++] = &add_rx;
+	add_uevents[i++] = &add_tx;
+	add_uevents[i++] = NULL;
+
 	if (kconfig.choice == 'y')
-		uevents[i++] = &rem_rx;
-	uevents[i++] = &rem_tx;
-	uevents[i++] = &rem;
-	uevents[i++] = NULL;
+		rem_uevents[j++] = &rem_rx;
+	rem_uevents[j++] = &rem_tx;
+	rem_uevents[j++] = &rem;
+	rem_uevents[j++] = NULL;
 }
 
 static struct tst_test test = {
-- 
2.55.0


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

  reply	other threads:[~2026-08-28 15:26 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25 17:14 [LTP] [PATCH] uevent02: Make wait_for_uevents() order-independent Avinesh Kumar via ltp
2026-08-25 17:36 ` [LTP] " linuxtestproject.agent
2026-08-28 15:26   ` Avinesh Kumar via ltp [this message]
2026-08-28 21:09     ` linuxtestproject.agent
2026-09-03 13:25     ` [LTP] [PATCH v2] " Andrea Cervesato via ltp
2026-09-03 14:42     ` Cyril Hrubis
2026-09-07 19:44       ` [LTP] [PATCH v3] " Avinesh Kumar via ltp
2026-09-07 22:01         ` [LTP] " linuxtestproject.agent

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260828152631.254653-1-avinesh.kumar@suse.com \
    --to=ltp@lists.linux.it \
    --cc=avinesh.kumar@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.