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
next prev 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®