mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: wen.yang@linux.dev
To: Gabriele Monaco <gmonaco@redhat.com>
Cc: Nam Cao <namcao@linutronix.de>,
	linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Wen Yang <wen.yang@linux.dev>
Subject: [PATCH v5 3/5] rv/reactors: export rv_register_reactor() and rv_unregister_reactor()
Date: Mon,  7 Sep 2026 01:10:39 +0800	[thread overview]
Message-ID: <7c931773dacd7c3da35a22629c3d7dc286b5a0fe.1788705281.git.wen.yang@linux.dev> (raw)
In-Reply-To: <cover.1788705281.git.wen.yang@linux.dev>

From: Wen Yang <wen.yang@linux.dev>

rv_react() is exported to modules, but the reactor registration helpers
are not.  Export them with EXPORT_SYMBOL_GPL() so reactor modules and
the tristate KUnit test module can register and unregister reactors
without hitting undefined symbol errors at link time(modpost).

Commit 3d3800b4f7f4 ("rv: Remove reactor's reference counter") noted
that if module-based reactors are supported, try_module_get()/module_put()
should be used. Add struct module *owner to struct rv_reactor so a module
cat set owner = THIS_MODULE; pin the module in monitor_swap_reactors_gingle()
and release it when a monitor detaches or is unregistered.

In-tree reactors leave owner = NULL and are unaffected.

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Wen Yang <wen.yang@linux.dev>
---
 include/linux/rv.h            |  3 +++
 kernel/trace/rv/rv.c          |  5 +++++
 kernel/trace/rv/rv_reactors.c | 38 +++++++++++++++++++++++++++++------
 3 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/include/linux/rv.h b/include/linux/rv.h
index 541ba404926a..ff3289ba4f02 100644
--- a/include/linux/rv.h
+++ b/include/linux/rv.h
@@ -128,10 +128,13 @@ union rv_task_monitor {
 };
 
 #ifdef CONFIG_RV_REACTORS
+struct module;
+
 struct rv_reactor {
 	const char		*name;
 	const char		*description;
 	__printf(1, 0) void	(*react)(const char *msg, va_list args);
+	struct module		*owner;
 	struct list_head	list;
 };
 #endif
diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c
index 29f155c6968b..458b17c005b3 100644
--- a/kernel/trace/rv/rv.c
+++ b/kernel/trace/rv/rv.c
@@ -803,6 +803,11 @@ int rv_unregister_monitor(struct rv_monitor *monitor)
 	guard(mutex)(&rv_interface_lock);
 
 	rv_disable_monitor(monitor);
+#ifdef CONFIG_RV_REACTORS
+	if (monitor->reactor)
+		module_put(monitor->reactor->owner);
+
+#endif
 	list_del(&monitor->list);
 	destroy_monitor_dir(monitor);
 
diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c
index ff7d478227c3..136eb7f47c4a 100644
--- a/kernel/trace/rv/rv_reactors.c
+++ b/kernel/trace/rv/rv_reactors.c
@@ -62,6 +62,7 @@
  */
 
 #include <linux/lockdep.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
 #include "rv.h"
@@ -159,7 +160,7 @@ static const struct seq_operations monitor_reactors_seq_ops = {
 	.show	= monitor_reactor_show
 };
 
-static void monitor_swap_reactors_single(struct rv_monitor *mon,
+static int monitor_swap_reactors_single(struct rv_monitor *mon,
 					 struct rv_reactor *reactor,
 					 bool nested)
 {
@@ -167,29 +168,39 @@ static void monitor_swap_reactors_single(struct rv_monitor *mon,
 
 	/* nothing to do */
 	if (mon->reactor == reactor)
-		return;
+		return 0;
+
+	if (reactor->owner && !try_module_get(reactor->owner))
+		return -EBUSY;
 
 	monitor_enabled = mon->enabled;
 	if (monitor_enabled)
 		rv_disable_monitor(mon);
 
+	if (mon->reactor)
+		module_put(mon->reactor->owner);
 	mon->reactor = reactor;
 	mon->react = reactor->react;
 
 	/* enable only once if iterating through a container */
 	if (monitor_enabled && !nested)
 		rv_enable_monitor(mon);
+
+	return 0;
 }
 
-static void monitor_swap_reactors(struct rv_monitor *mon, struct rv_reactor *reactor)
+static int monitor_swap_reactors(struct rv_monitor *mon, struct rv_reactor *reactor)
 {
 	struct rv_monitor *p = mon;
+	int ret;
 
 	if (rv_is_container_monitor(mon))
 		list_for_each_entry_continue(p, &rv_monitors_list, list) {
 			if (p->parent != mon)
 				break;
-			monitor_swap_reactors_single(p, reactor, true);
+			ret = monitor_swap_reactors_single(p, reactor, true);
+			if (ret)
+				return ret;
 		}
 	/*
 	 * This call enables and disables the monitor if they were active.
@@ -197,7 +208,7 @@ static void monitor_swap_reactors(struct rv_monitor *mon, struct rv_reactor *rea
 	 * All nested monitors are enabled also if they were off, we may refine
 	 * this logic in the future.
 	 */
-	monitor_swap_reactors_single(mon, reactor, false);
+	return monitor_swap_reactors_single(mon, reactor, false);
 }
 
 static ssize_t
@@ -236,10 +247,14 @@ monitor_reactors_write(struct file *file, const char __user *user_buf,
 	guard(mutex)(&rv_interface_lock);
 
 	list_for_each_entry(reactor, &rv_reactors_list, list) {
+		int ret;
+
 		if (strcmp(ptr, reactor->name) != 0)
 			continue;
 
-		monitor_swap_reactors(mon, reactor);
+		ret = monitor_swap_reactors(mon, reactor);
+		if (ret)
+			return ret;
 
 		return count;
 	}
@@ -314,6 +329,7 @@ int rv_register_reactor(struct rv_reactor *reactor)
 	guard(mutex)(&rv_interface_lock);
 	return __rv_register_reactor(reactor);
 }
+EXPORT_SYMBOL_GPL(rv_register_reactor);
 
 /**
  * rv_unregister_reactor - unregister a rv reactor.
@@ -327,6 +343,7 @@ int rv_unregister_reactor(struct rv_reactor *reactor)
 	list_del(&reactor->list);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rv_unregister_reactor);
 
 /*
  * reacting_on interface.
@@ -421,6 +438,15 @@ int reactor_populate_monitor(struct rv_monitor *mon, struct dentry *root)
 	 * Configure as the rv_nop reactor.
 	 */
 	mon->reactor = get_reactor_rdef_by_name("nop");
+	if (WARN_ON(!mon->reactor)) {
+		rv_remove(tmp);
+		return -EINVAL;
+	}
+
+	if (mon->reactor->owner && !try_module_get(mon->reactor->owner)) {
+		rv_remove(tmp);
+		return -EBUSY;
+	}
 
 	return 0;
 }
-- 
2.25.1


  parent reply	other threads:[~2026-09-06 17:11 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-06 17:10 [PATCH v5 0/5] rv/reactors: fix lockdep warning and add tests wen.yang
2026-09-06 17:10 ` [PATCH v5 1/5] rv/reactors: use LD_WAIT_SPIN as the reactor lockdep wait type wen.yang
2026-09-06 17:10 ` [PATCH v5 2/5] rv/reactors: propagate rv_register_reactor() error from reactor init wen.yang
2026-09-06 17:10 ` wen.yang [this message]
2026-09-11  6:53   ` [PATCH v5 3/5] rv/reactors: export rv_register_reactor() and rv_unregister_reactor() Gabriele Monaco
2026-09-06 17:10 ` [PATCH v5 4/5] rv/reactors: add KUnit tests for reactor registration and dispatch wen.yang
2026-09-06 17:10 ` [PATCH v5 5/5] selftests/verification: Test loadable module-based reactor wen.yang

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=7c931773dacd7c3da35a22629c3d7dc286b5a0fe.1788705281.git.wen.yang@linux.dev \
    --to=wen.yang@linux.dev \
    --cc=gmonaco@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=namcao@linutronix.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®