From: Jeff Barnes <jeffbarnes@linux.microsoft.com>
To: linux-trace-kernel@vger.kernel.org
Cc: mhiramat@kernel.org, rostedt@goodmis.org, mathieu.desnoyers@efficios.com
Subject: [PATCH v2 2/2] tracing/user_events: Share tracing state between existing threads
Date: Mon, 5 Oct 2026 10:39:44 -0400 [thread overview]
Message-ID: <20261005143944.752112-3-jeffbarnes@linux.microsoft.com> (raw)
In-Reply-To: <20261005143944.752112-1-jeffbarnes@linux.microsoft.com>
Threads created before the first user-events registration can share an
mm_struct while each has a NULL user_event_mm pointer.
When one thread registers an event, current_user_event_mm() creates a
user_event_mm and attaches it only to that task. A pre-existing sibling
thread sharing the same mm_struct can later create another user_event_mm.
The two wrappers have independent enabler lists, allowing both threads to
register different events using the same enable address and bit despite
the EADDRINUSE check.
Look for an active user_event_mm associated with the current mm_struct
before allocating a new one. Attach the current task to that wrapper and
increment its task count.
Serialize lookup and attachment with the final task-count decrement and
list removal so that a task cannot attach to a wrapper after its
last-task transition has begun.
Without this change, the new selftest reports that the second
registration succeeds. With the change, it is rejected with
EADDRINUSE, and all user_events ABI tests pass.
Signed-off-by: Jeff Barnes <jeffbarnes@linux.microsoft.com>
---
kernel/trace/trace_events_user.c | 78 ++++++++++++++++++++++++++------
1 file changed, 64 insertions(+), 14 deletions(-)
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index f658c3a77aa7..950d8a3cd0e3 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -210,6 +210,7 @@ static int user_event_parse(struct user_event_group *group, char *name,
static struct user_event_mm *user_event_mm_get(struct user_event_mm *mm);
static struct user_event_mm *user_event_mm_get_all(struct user_event *user);
+static void user_event_mm_destroy(struct user_event_mm *mm);
static void user_event_mm_put(struct user_event_mm *mm);
static int destroy_user_event(struct user_event *user);
static bool user_fields_match(struct user_event *user, int argc,
@@ -754,33 +755,78 @@ static struct user_event_mm *user_event_mm_alloc(struct task_struct *t)
return user_mm;
}
+static struct user_event_mm *
+user_event_mm_find_locked(struct mm_struct *mm)
+{
+ struct user_event_mm *user_mm;
+
+ lockdep_assert_held(&user_event_mms_lock);
+
+ list_for_each_entry(user_mm, &user_event_mms, mms_link)
+ if (user_mm->mm == mm)
+ return user_mm;
+
+ return NULL;
+}
+
static void user_event_mm_attach(struct user_event_mm *user_mm, struct task_struct *t)
{
unsigned long flags;
spin_lock_irqsave(&user_event_mms_lock, flags);
list_add_rcu(&user_mm->mms_link, &user_event_mms);
- spin_unlock_irqrestore(&user_event_mms_lock, flags);
-
t->user_event_mm = user_mm;
+ spin_unlock_irqrestore(&user_event_mms_lock, flags);
}
static struct user_event_mm *current_user_event_mm(void)
{
+ struct user_event_mm *new_mm;
struct user_event_mm *user_mm = current->user_event_mm;
+ unsigned long flags;
if (user_mm)
- goto inc;
+ return user_event_mm_get(user_mm);
- user_mm = user_event_mm_alloc(current);
+ spin_lock_irqsave(&user_event_mms_lock, flags);
- if (!user_mm)
- goto error;
+ user_mm = user_event_mm_find_locked(current->mm);
+
+ if (user_mm) {
+ refcount_inc(&user_mm->tasks);
+ current->user_event_mm = user_mm;
+ user_event_mm_get(user_mm);
+ }
+
+ spin_unlock_irqrestore(&user_event_mms_lock, flags);
+
+ if (user_mm)
+ return user_mm;
+
+ new_mm = user_event_mm_alloc(current);
+
+ spin_lock_irqsave(&user_event_mms_lock, flags);
+
+ user_mm = user_event_mm_find_locked(current->mm);
+
+ if (user_mm) {
+ refcount_inc(&user_mm->tasks);
+ } else if (new_mm) {
+ user_mm = new_mm;
+ list_add_rcu(&user_mm->mms_link, &user_event_mms);
+ } else {
+ spin_unlock_irqrestore(&user_event_mms_lock, flags);
+ return NULL;
+ }
+
+ current->user_event_mm = user_mm;
+ user_event_mm_get(user_mm);
+
+ spin_unlock_irqrestore(&user_event_mms_lock, flags);
+
+ if (new_mm && new_mm != user_mm)
+ user_event_mm_destroy(new_mm);
- user_event_mm_attach(user_mm, current);
-inc:
- refcount_inc(&user_mm->refcnt);
-error:
return user_mm;
}
@@ -817,14 +863,18 @@ void user_event_mm_remove(struct task_struct *t)
might_sleep();
mm = t->user_event_mm;
+
+ spin_lock_irqsave(&user_event_mms_lock, flags);
+
t->user_event_mm = NULL;
- /* Clone will increment the tasks, only remove if last clone */
- if (!refcount_dec_and_test(&mm->tasks))
+ /* Clones and attached tasks increment this count. */
+ if (!refcount_dec_and_test(&mm->tasks)) {
+ spin_unlock_irqrestore(&user_event_mms_lock, flags);
return;
+ }
- /* Remove the mm from the list, so it can no longer be enabled */
- spin_lock_irqsave(&user_event_mms_lock, flags);
+ /* Prevent new tasks from attaching after the last-task transition. */
list_del_rcu(&mm->mms_link);
spin_unlock_irqrestore(&user_event_mms_lock, flags);
--
2.43.0
next prev parent reply other threads:[~2026-10-05 14:39 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-02 15:39 [PATCH 0/2] tracing/user_events: Share state between existing threads Jeff Barnes
2026-10-02 15:39 ` [PATCH 1/2] selftests/user_events: Test registration from " Jeff Barnes
2026-10-03 1:33 ` sashiko-bot
2026-10-02 15:39 ` [PATCH 2/2] tracing/user_events: Share tracing state between " Jeff Barnes
2026-10-05 14:39 ` [PATCH v2 0/2] " Jeff Barnes
2026-10-05 14:39 ` [PATCH v2 1/2] selftests/user_events: Test registration from " Jeff Barnes
2026-10-05 14:39 ` Jeff Barnes [this message]
2026-10-06 16:47 ` [PATCH v2 0/3] tracing/user_events: Share state with " Jeff Barnes
2026-10-06 16:47 ` [PATCH v2 1/3] tracing/user_events: Serialize duplicate enabler lookup with event removal Jeff Barnes
2026-10-06 16:47 ` [PATCH v2 2/3] tracing/user_events: Share event state with existing threads Jeff Barnes
2026-10-06 16:47 ` [PATCH v2 3/3] selftests/user_events: Test registration from " Jeff Barnes
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=20261005143944.752112-3-jeffbarnes@linux.microsoft.com \
--to=jeffbarnes@linux.microsoft.com \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
/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.