* [LTP] [PATCH] uevent02: Make wait_for_uevents() order-independent
@ 2026-08-25 17:14 Avinesh Kumar via ltp
2026-08-25 17:36 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 8+ messages in thread
From: Avinesh Kumar via ltp @ 2026-08-25 17:14 UTC (permalink / raw)
To: ltp
From: Avinesh Kumar <avinesh.kumar@suse.com>
Commit 8e63c9e6179a ("net: Defer netdev KOBJ_ADD uevent until the
device is published")[0] in kernel v7.2 changed register_netdevice()
to emit a network interface's own "add" uevent only after the
interface is fully registered, instead of before its queue kobjects
are created. This flips 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() matched events strictly in the order given in the
uevents array, so on kernels with the reordered uevents the "add(net)"
event only matches once the rx/tx queue events have already been
consumed from the socket, leaving wait_for_uevents() stuck waiting for
events that already went by, until uevent02 times out and fails.
Since the relative order of unrelated uevents is a kernel
implementation detail the test should not depend on, make
wait_for_uevents() track the still-unmatched events in a pending set
and match incoming uevents against any of them, regardless of
position.
[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 | 37 ++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/testcases/kernel/uevents/uevent.h b/testcases/kernel/uevents/uevent.h
index 1ad092d5ea39..b4e4fce2b2f5 100644
--- a/testcases/kernel/uevents/uevent.h
+++ b/testcases/kernel/uevents/uevent.h
@@ -117,15 +117,30 @@ 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.
*/
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,14 +151,20 @@ 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;
}
}
}
+
+ close(fd);
}
/*
--
2.55.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [LTP] uevent02: Make wait_for_uevents() order-independent 2026-08-25 17:14 [LTP] [PATCH] uevent02: Make wait_for_uevents() order-independent Avinesh Kumar via ltp @ 2026-08-25 17:36 ` linuxtestproject.agent 2026-08-28 15:26 ` [LTP] [PATCH v2] " Avinesh Kumar via ltp 0 siblings, 1 reply; 8+ messages in thread From: linuxtestproject.agent @ 2026-08-25 17:36 UTC (permalink / raw) To: Avinesh Kumar; +Cc: ltp Hi Avinesh, On Tue, 25 Aug 2026, Avinesh Kumar wrote: > uevent02: Make wait_for_uevents() order-independent > + 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; > } > } Could this preserve ordering between dependent lifecycle phases? The callers put add and remove events for the same objects in one array. Matching every pending entry means that a remove received before its add is accepted, causing the test to pass despite an invalid lifecycle order. The kernel change only requires the interface and queue add events to be order-independent. Could each independent group be matched without order while retaining the ordering between the add and remove phases? Verdict - Needs revision --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 8+ messages in thread
* [LTP] [PATCH v2] uevent02: Make wait_for_uevents() order-independent 2026-08-25 17:36 ` [LTP] " linuxtestproject.agent @ 2026-08-28 15:26 ` Avinesh Kumar via ltp 2026-08-28 21:09 ` [LTP] " linuxtestproject.agent ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Avinesh Kumar via ltp @ 2026-08-28 15:26 UTC (permalink / raw) To: ltp 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 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] uevent02: Make wait_for_uevents() order-independent 2026-08-28 15:26 ` [LTP] [PATCH v2] " Avinesh Kumar via ltp @ 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 2 siblings, 0 replies; 8+ messages in thread From: linuxtestproject.agent @ 2026-08-28 21:09 UTC (permalink / raw) To: Avinesh Kumar; +Cc: ltp Hi Avinesh, On Fri, 28 Aug 2026, Avinesh Kumar wrote: > uevent02: Make wait_for_uevents() order-independent Verdict - Reviewed --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v2] uevent02: Make wait_for_uevents() order-independent 2026-08-28 15:26 ` [LTP] [PATCH v2] " Avinesh Kumar via ltp 2026-08-28 21:09 ` [LTP] " linuxtestproject.agent @ 2026-09-03 13:25 ` Andrea Cervesato via ltp 2026-09-03 14:42 ` Cyril Hrubis 2 siblings, 0 replies; 8+ messages in thread From: Andrea Cervesato via ltp @ 2026-09-03 13:25 UTC (permalink / raw) To: Avinesh Kumar; +Cc: ltp Acked-by: Andrea Cervesato <andrea.cervesato@suse.com> -- Andrea Cervesato SUSE QE Automation Engineer Linux andrea.cervesato@suse.com -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v2] uevent02: Make wait_for_uevents() order-independent 2026-08-28 15:26 ` [LTP] [PATCH v2] " Avinesh Kumar via ltp 2026-08-28 21:09 ` [LTP] " 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 2 siblings, 1 reply; 8+ messages in thread From: Cyril Hrubis @ 2026-09-03 14:42 UTC (permalink / raw) To: Avinesh Kumar; +Cc: ltp Hi! > 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; We can as well count the uevents[] first, then create the pending[] array with the cnt. Also I would have used array of bitflags. while (uevents[cnt]) cnt++; uint8_t not_pending[cnt] = {}; ... if (not_pending[i]) continue; if (uevent_match(buf, len, uevents[i])) { not_pendig[i] = 1; ... } With that we avoid copying the pointers and static limit. But that is largerly cosmetic changes. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 8+ messages in thread
* [LTP] [PATCH v3] uevent02: Make wait_for_uevents() order-independent 2026-09-03 14:42 ` Cyril Hrubis @ 2026-09-07 19:44 ` Avinesh Kumar via ltp 2026-09-07 22:01 ` [LTP] " linuxtestproject.agent 0 siblings, 1 reply; 8+ messages in thread From: Avinesh Kumar via ltp @ 2026-09-07 19:44 UTC (permalink / raw) To: ltp 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 | 29 +++++++++++++-------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/testcases/kernel/uevents/uevent.h b/testcases/kernel/uevents/uevent.h index 1ad092d5ea39..495c1254ff10 100644 --- a/testcases/kernel/uevents/uevent.h +++ b/testcases/kernel/uevents/uevent.h @@ -6,6 +6,8 @@ #ifndef UEVENT_H__ #define UEVENT_H__ +#include <stdint.h> +#include <string.h> #include "tst_netlink.h" /* @@ -119,13 +121,30 @@ static inline int open_uevent_netlink(void) /* * 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; + int i, cnt = 0, remaining; + + while (uevents[cnt]) + cnt++; + + uint8_t matched[cnt]; + + memset(matched, 0, sizeof(matched)); - while (1) { + remaining = cnt; + + 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 (matched[i]) + continue; + + if (uevent_match(buf, len, uevents[i])) { + tst_res(TPASS, "Got expected UEVENT"); + matched[i] = 1; + remaining--; + break; } } } diff --git a/testcases/kernel/uevents/uevent02.c b/testcases/kernel/uevents/uevent02.c index 1135f55a87db..a48239d2a40e 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,9 @@ 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 +117,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 +133,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 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] uevent02: Make wait_for_uevents() order-independent 2026-09-07 19:44 ` [LTP] [PATCH v3] " Avinesh Kumar via ltp @ 2026-09-07 22:01 ` linuxtestproject.agent 0 siblings, 0 replies; 8+ messages in thread From: linuxtestproject.agent @ 2026-09-07 22:01 UTC (permalink / raw) To: Avinesh Kumar; +Cc: ltp Hi Avinesh, On September 7, 2026, Avinesh Kumar wrote: > uevent02: Make wait_for_uevents() order-independent Verdict - Reviewed --- Note: The agent can sometimes produce false positives although often its findings are genuine. If you find issues with the review, please comment this email or ignore the suggestions. Regards, LTP AI Reviewer -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-07 22:01 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 ` [LTP] [PATCH v2] " Avinesh Kumar via ltp 2026-08-28 21:09 ` [LTP] " 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox