From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Andrew Morton <akpm@linux-foundation.org>,
Beau Belgrave <beaub@linux.microsoft.com>
Subject: [for-linus][PATCH 11/15] tracing/user_events: Track refcount consistently via put/get
Date: Thu, 15 Jun 2023 09:05:42 -0400 [thread overview]
Message-ID: <20230615133416.895403445@goodmis.org> (raw)
In-Reply-To: 20230615130531.200384328@goodmis.org
From: Beau Belgrave <beaub@linux.microsoft.com>
Various parts of the code today track user_event's refcnt field directly
via a refcount_add/dec. This makes it hard to modify the behavior of the
last reference decrement in all code paths consistently. For example, in
the future we will auto-delete events upon the last reference going
away. This last reference could happen in many places, but we want it to
be consistently handled.
Add user_event_get() and user_event_put() for the add/dec. Update all
places where direct refcounts are being used to utilize these new
functions. In each location pass if event_mutex is locked or not. This
allows us to drop events automatically in future patches clearly. Ensure
when caller states the lock is held, it really is (or is not) held.
Link: https://lkml.kernel.org/r/20230614163336.5797-3-beaub@linux.microsoft.com
Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
kernel/trace/trace_events_user.c | 69 +++++++++++++++++++-------------
1 file changed, 41 insertions(+), 28 deletions(-)
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index 629823e21447..c064458eea5c 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -177,6 +177,28 @@ static u32 user_event_key(char *name)
return jhash(name, strlen(name), 0);
}
+static struct user_event *user_event_get(struct user_event *user)
+{
+ refcount_inc(&user->refcnt);
+
+ return user;
+}
+
+static void user_event_put(struct user_event *user, bool locked)
+{
+#ifdef CONFIG_LOCKDEP
+ if (locked)
+ lockdep_assert_held(&event_mutex);
+ else
+ lockdep_assert_not_held(&event_mutex);
+#endif
+
+ if (unlikely(!user))
+ return;
+
+ refcount_dec(&user->refcnt);
+}
+
static void user_event_group_destroy(struct user_event_group *group)
{
kfree(group->system_name);
@@ -228,12 +250,13 @@ static struct user_event_group *user_event_group_create(void)
return NULL;
};
-static void user_event_enabler_destroy(struct user_event_enabler *enabler)
+static void user_event_enabler_destroy(struct user_event_enabler *enabler,
+ bool locked)
{
list_del_rcu(&enabler->mm_enablers_link);
/* No longer tracking the event via the enabler */
- refcount_dec(&enabler->event->refcnt);
+ user_event_put(enabler->event, locked);
kfree(enabler);
}
@@ -295,7 +318,7 @@ static void user_event_enabler_fault_fixup(struct work_struct *work)
/* User asked for enabler to be removed during fault */
if (test_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler))) {
- user_event_enabler_destroy(enabler);
+ user_event_enabler_destroy(enabler, true);
goto out;
}
@@ -470,14 +493,12 @@ static bool user_event_enabler_dup(struct user_event_enabler *orig,
if (!enabler)
return false;
- enabler->event = orig->event;
+ enabler->event = user_event_get(orig->event);
enabler->addr = orig->addr;
/* Only dup part of value (ignore future flags, etc) */
enabler->values = orig->values & ENABLE_VAL_DUP_MASK;
- refcount_inc(&enabler->event->refcnt);
-
/* Enablers not exposed yet, RCU not required */
list_add(&enabler->mm_enablers_link, &mm->enablers);
@@ -594,7 +615,7 @@ static void user_event_mm_destroy(struct user_event_mm *mm)
struct user_event_enabler *enabler, *next;
list_for_each_entry_safe(enabler, next, &mm->enablers, mm_enablers_link)
- user_event_enabler_destroy(enabler);
+ user_event_enabler_destroy(enabler, false);
mmdrop(mm->mm);
kfree(mm);
@@ -749,7 +770,7 @@ static struct user_event_enabler
* exit or run exec(), which includes forks and clones.
*/
if (!*write_result) {
- refcount_inc(&enabler->event->refcnt);
+ user_event_get(user);
list_add_rcu(&enabler->mm_enablers_link, &user_mm->enablers);
}
@@ -1337,10 +1358,8 @@ static struct user_event *find_user_event(struct user_event_group *group,
*outkey = key;
hash_for_each_possible(group->register_table, user, node, key)
- if (!strcmp(EVENT_NAME(user), name)) {
- refcount_inc(&user->refcnt);
- return user;
- }
+ if (!strcmp(EVENT_NAME(user), name))
+ return user_event_get(user);
return NULL;
}
@@ -1554,12 +1573,12 @@ static int user_event_reg(struct trace_event_call *call,
return ret;
inc:
- refcount_inc(&user->refcnt);
+ user_event_get(user);
update_enable_bit_for(user);
return 0;
dec:
update_enable_bit_for(user);
- refcount_dec(&user->refcnt);
+ user_event_put(user, true);
return 0;
}
@@ -1593,7 +1612,7 @@ static int user_event_create(const char *raw_command)
ret = user_event_parse_cmd(group, name, &user, 0);
if (!ret)
- refcount_dec(&user->refcnt);
+ user_event_put(user, false);
mutex_unlock(&group->reg_mutex);
@@ -1794,7 +1813,7 @@ static int user_event_parse(struct user_event_group *group, char *name,
return 0;
error:
- refcount_dec(&user->refcnt);
+ user_event_put(user, false);
return ret;
}
@@ -1883,7 +1902,7 @@ static int delete_user_event(struct user_event_group *group, char *name)
if (!user)
return -ENOENT;
- refcount_dec(&user->refcnt);
+ user_event_put(user, true);
if (!user_event_last_ref(user))
return -EBUSY;
@@ -2042,9 +2061,7 @@ static int user_events_ref_add(struct user_event_file_info *info,
for (i = 0; i < count; ++i)
new_refs->events[i] = refs->events[i];
- new_refs->events[i] = user;
-
- refcount_inc(&user->refcnt);
+ new_refs->events[i] = user_event_get(user);
rcu_assign_pointer(info->refs, new_refs);
@@ -2158,7 +2175,7 @@ static long user_events_ioctl_reg(struct user_event_file_info *info,
ret = user_events_ref_add(info, user);
/* No longer need parse ref, ref_add either worked or not */
- refcount_dec(&user->refcnt);
+ user_event_put(user, false);
/* Positive number is index and valid */
if (ret < 0)
@@ -2307,7 +2324,7 @@ static long user_events_ioctl_unreg(unsigned long uarg)
set_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler));
if (!test_bit(ENABLE_VAL_FAULTING_BIT, ENABLE_BITOPS(enabler)))
- user_event_enabler_destroy(enabler);
+ user_event_enabler_destroy(enabler, true);
/* Removed at least one */
ret = 0;
@@ -2365,7 +2382,6 @@ static int user_events_release(struct inode *node, struct file *file)
struct user_event_file_info *info = file->private_data;
struct user_event_group *group;
struct user_event_refs *refs;
- struct user_event *user;
int i;
if (!info)
@@ -2389,12 +2405,9 @@ static int user_events_release(struct inode *node, struct file *file)
* The underlying user_events are ref counted, and cannot be freed.
* After this decrement, the user_events may be freed elsewhere.
*/
- for (i = 0; i < refs->count; ++i) {
- user = refs->events[i];
+ for (i = 0; i < refs->count; ++i)
+ user_event_put(refs->events[i], false);
- if (user)
- refcount_dec(&user->refcnt);
- }
out:
file->private_data = NULL;
--
2.39.2
next prev parent reply other threads:[~2023-06-15 13:36 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-15 13:05 [for-linus][PATCH 00/15] tracing: Updates for 6.4 Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 01/15] tracing/rv/rtla: Update MAINTAINERS file to point to proper mailing list Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 02/15] tracing/user_events: Prevent same name but different args event Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 03/15] tracing/user_events: Handle matching arguments that is null from dyn_events Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 04/15] tracing: Modify print_fields() for fields output order Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 05/15] tracing/user_events: Fix the incorrect trace record for empty arguments events Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 06/15] selftests/user_events: Add ftrace self-test " Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 07/15] selftests/user_events: Clear the events after perf self-test Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 08/15] selftests/user_events: Add perf self-test for empty arguments events Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 09/15] tracing/user_events: Remove user_ns walk for groups Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 10/15] tracing/user_events: Store register flags on events Steven Rostedt
2023-06-15 13:05 ` Steven Rostedt [this message]
2023-06-15 13:05 ` [for-linus][PATCH 12/15] tracing/user_events: Add auto cleanup and future persist flag Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 13/15] selftests/user_events: Ensure auto cleanup works as expected Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 14/15] selftests/user_events: Adapt dyn_test to non-persist events Steven Rostedt
2023-06-15 13:05 ` [for-linus][PATCH 15/15] tracing/user_events: Document auto-cleanup and remove dyn_event refs Steven Rostedt
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=20230615133416.895403445@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=beaub@linux.microsoft.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mhiramat@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox