All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free
@ 2025-01-05 12:47 Masami Hiramatsu (Google)
  2025-01-05 12:47 ` [PATCH v2 1/6] tracing/kprobes: Fix to free objects when failed to copy a symbol Masami Hiramatsu (Google)
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:47 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

Hi,

Here is the 2nd version of the series to fix and cleanup probe events in
ftrace with __free().
Fix [2/6] according to Oleg's comment to check the argument and add
cleanup.h, update [3/6] to apply it cleanly on probes/for-next, and fix 
[5/6] to assign NULL to 'tk' instead of using no_free_ptr() after
registering it successfully to avoid __must_check_fn warning.

Thanks,

---

Masami Hiramatsu (Google) (6):
      tracing/kprobes: Fix to free objects when failed to copy a symbol
      Provide __free(argv) for argv_split() users
      tracing: Use __free() for argv in dynevent
      tracing: Use __free() in trace_probe for cleanup
      tracing: Use __free() for kprobe events to cleanup
      tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos


 include/linux/string.h        |    3 +
 kernel/trace/trace_dynevent.c |   23 +++----
 kernel/trace/trace_kprobe.c   |  127 ++++++++++++++++++++---------------------
 kernel/trace/trace_probe.c    |   52 ++++++-----------
 4 files changed, 91 insertions(+), 114 deletions(-)

--
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v2 1/6] tracing/kprobes: Fix to free objects when failed to copy a symbol
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
@ 2025-01-05 12:47 ` Masami Hiramatsu (Google)
  2025-01-05 12:47 ` [PATCH v2 2/6] Provide __free(argv) for argv_split() users Masami Hiramatsu (Google)
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:47 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

In __trace_kprobe_create(), if something fails it must goto error block
to free objects. But when strdup() a symbol, it returns without that.
Fix it to goto the error block to free objects correctly.

Fixes: 6212dd29683e ("tracing/kprobes: Use dyn_event framework for kprobe events")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 kernel/trace/trace_kprobe.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index bae26eb14449..4c3e316454a0 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -935,8 +935,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		}
 		/* a symbol specified */
 		symbol = kstrdup(argv[1], GFP_KERNEL);
-		if (!symbol)
-			return -ENOMEM;
+		if (!symbol) {
+			ret = -ENOMEM;
+			goto error;
+		}
 
 		tmp = strchr(symbol, '%');
 		if (tmp) {


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 2/6] Provide __free(argv) for argv_split() users
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
  2025-01-05 12:47 ` [PATCH v2 1/6] tracing/kprobes: Fix to free objects when failed to copy a symbol Masami Hiramatsu (Google)
@ 2025-01-05 12:47 ` Masami Hiramatsu (Google)
  2025-01-05 14:14   ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Oleg Nesterov
  2025-01-05 12:48 ` [PATCH v2 3/6] tracing: Use __free() for argv in dynevent Masami Hiramatsu (Google)
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:47 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Provide __free(argv) macro for argv_split() users so that they can
avoid gotos.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v2:
  - Fix to call argv_free() only if the argument is !IS_ERR_OR_NULL().
  - Add including cleanup.h.
---
 include/linux/string.h |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 493ac4862c77..07f2a90d5d9c 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -4,6 +4,7 @@
 
 #include <linux/args.h>
 #include <linux/array_size.h>
+#include <linux/cleanup.h>	/* for DEFINE_FREE() */
 #include <linux/compiler.h>	/* for inline */
 #include <linux/types.h>	/* for size_t */
 #include <linux/stddef.h>	/* for NULL */
@@ -312,6 +313,8 @@ extern void *kmemdup_array(const void *src, size_t count, size_t element_size, g
 extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
 extern void argv_free(char **argv);
 
+DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
+
 /* lib/cmdline.c */
 extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 3/6] tracing: Use __free() for argv in dynevent
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
  2025-01-05 12:47 ` [PATCH v2 1/6] tracing/kprobes: Fix to free objects when failed to copy a symbol Masami Hiramatsu (Google)
  2025-01-05 12:47 ` [PATCH v2 2/6] Provide __free(argv) for argv_split() users Masami Hiramatsu (Google)
@ 2025-01-05 12:48 ` Masami Hiramatsu (Google)
  2025-01-05 12:48 ` [PATCH v2 4/6] tracing: Use __free() in trace_probe for cleanup Masami Hiramatsu (Google)
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:48 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Use __free() for the args allocated by argv_split() in dynevent.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v2:
  - Rebased on probes/for-next, which reverts previous dynevent guard patch.
---
 kernel/trace/trace_dynevent.c |   23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index 4376887e0d8a..630d9695b2df 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -74,24 +74,20 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
 	struct dyn_event *pos, *n;
 	char *system = NULL, *event, *p;
 	int argc, ret = -ENOENT;
-	char **argv;
+	char **argv __free(argv) = NULL;
 
 	argv = argv_split(GFP_KERNEL, raw_command, &argc);
 	if (!argv)
 		return -ENOMEM;
 
 	if (argv[0][0] == '-') {
-		if (argv[0][1] != ':') {
-			ret = -EINVAL;
-			goto out;
-		}
+		if (argv[0][1] != ':')
+			return -EINVAL;
 		event = &argv[0][2];
 	} else {
 		event = strchr(argv[0], ':');
-		if (!event) {
-			ret = -EINVAL;
-			goto out;
-		}
+		if (!event)
+			return -EINVAL;
 		event++;
 	}
 
@@ -101,10 +97,8 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
 		event = p + 1;
 		*p = '\0';
 	}
-	if (!system && event[0] == '\0') {
-		ret = -EINVAL;
-		goto out;
-	}
+	if (!system && event[0] == '\0')
+		return -EINVAL;
 
 	mutex_lock(&event_mutex);
 	for_each_dyn_event_safe(pos, n) {
@@ -120,8 +114,7 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
 	}
 	tracing_reset_all_online_cpus();
 	mutex_unlock(&event_mutex);
-out:
-	argv_free(argv);
+
 	return ret;
 }
 


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 4/6] tracing: Use __free() in trace_probe for cleanup
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
                   ` (2 preceding siblings ...)
  2025-01-05 12:48 ` [PATCH v2 3/6] tracing: Use __free() for argv in dynevent Masami Hiramatsu (Google)
@ 2025-01-05 12:48 ` Masami Hiramatsu (Google)
  2025-01-05 12:48 ` [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup Masami Hiramatsu (Google)
  2025-01-05 12:48 ` [PATCH v2 6/6] tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos Masami Hiramatsu (Google)
  5 siblings, 0 replies; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:48 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Use __free() in trace_probe to cleanup some gotos.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 kernel/trace/trace_probe.c |   52 +++++++++++++++-----------------------------
 1 file changed, 18 insertions(+), 34 deletions(-)

diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 16a5e368e7b7..bf6a7b81ae95 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -1409,7 +1409,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
 					   struct traceprobe_parse_context *ctx)
 {
 	struct fetch_insn *code, *tmp = NULL;
-	char *type, *arg;
+	char *type, *arg __free(kfree) = NULL;
 	int ret, len;
 
 	len = strlen(argv);
@@ -1426,22 +1426,16 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
 		return -ENOMEM;
 
 	parg->comm = kstrdup(arg, GFP_KERNEL);
-	if (!parg->comm) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!parg->comm)
+		return -ENOMEM;
 
 	type = parse_probe_arg_type(arg, parg, ctx);
-	if (IS_ERR(type)) {
-		ret = PTR_ERR(type);
-		goto out;
-	}
+	if (IS_ERR(type))
+		return PTR_ERR(type);
 
 	code = tmp = kcalloc(FETCH_INSN_MAX, sizeof(*code), GFP_KERNEL);
-	if (!code) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!code)
+		return -ENOMEM;
 	code[FETCH_INSN_MAX - 1].op = FETCH_OP_END;
 
 	ctx->last_type = NULL;
@@ -1497,8 +1491,6 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
 				kfree(code->data);
 	}
 	kfree(tmp);
-out:
-	kfree(arg);
 
 	return ret;
 }
@@ -1668,7 +1660,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 {
 	const struct btf_param *params = NULL;
 	int i, j, n, used, ret, args_idx = -1;
-	const char **new_argv = NULL;
+	const char **new_argv __free(kfree) = NULL;
 
 	ret = argv_has_var_arg(argc, argv, &args_idx, ctx);
 	if (ret < 0)
@@ -1707,7 +1699,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 				ret = sprint_nth_btf_arg(n, "", buf + used,
 							 bufsize - used, ctx);
 				if (ret < 0)
-					goto error;
+					return ERR_PTR(ret);
 
 				new_argv[j++] = buf + used;
 				used += ret + 1;
@@ -1721,25 +1713,20 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 			n = simple_strtoul(argv[i] + 4, &type, 10);
 			if (type && !(*type == ':' || *type == '\0')) {
 				trace_probe_log_err(0, BAD_VAR);
-				ret = -ENOENT;
-				goto error;
+				return ERR_PTR(-ENOENT);
 			}
 			/* Note: $argN starts from $arg1 */
 			ret = sprint_nth_btf_arg(n - 1, type, buf + used,
 						 bufsize - used, ctx);
 			if (ret < 0)
-				goto error;
+				return ERR_PTR(ret);
 			new_argv[j++] = buf + used;
 			used += ret + 1;
 		} else
 			new_argv[j++] = argv[i];
 	}
 
-	return new_argv;
-
-error:
-	kfree(new_argv);
-	return ERR_PTR(ret);
+	return_ptr(new_argv);
 }
 
 /* @buf: *buf must be equal to NULL. Caller must to free *buf */
@@ -1747,14 +1734,14 @@ int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf)
 {
 	int i, used, ret;
 	const int bufsize = MAX_DENTRY_ARGS_LEN;
-	char *tmpbuf = NULL;
+	char *tmpbuf __free(kfree) = NULL;
 
 	if (*buf)
 		return -EINVAL;
 
 	used = 0;
 	for (i = 0; i < argc; i++) {
-		char *tmp;
+		char *tmp __free(kfree) = NULL;
 		char *equal;
 		size_t arg_len;
 
@@ -1769,7 +1756,7 @@ int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf)
 
 		tmp = kstrdup(argv[i], GFP_KERNEL);
 		if (!tmp)
-			goto nomem;
+			return -ENOMEM;
 
 		equal = strchr(tmp, '=');
 		if (equal)
@@ -1790,18 +1777,15 @@ int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf)
 				       offsetof(struct file, f_path.dentry),
 				       equal ? equal + 1 : tmp);
 
-		kfree(tmp);
+		kfree(no_free_ptr(tmp));
 		if (ret >= bufsize - used)
-			goto nomem;
+			return -ENOMEM;
 		argv[i] = tmpbuf + used;
 		used += ret + 1;
 	}
 
-	*buf = tmpbuf;
+	*buf = no_free_ptr(tmpbuf);
 	return 0;
-nomem:
-	kfree(tmpbuf);
-	return -ENOMEM;
 }
 
 void traceprobe_finish_parse(struct traceprobe_parse_context *ctx)


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
                   ` (3 preceding siblings ...)
  2025-01-05 12:48 ` [PATCH v2 4/6] tracing: Use __free() in trace_probe for cleanup Masami Hiramatsu (Google)
@ 2025-01-05 12:48 ` Masami Hiramatsu (Google)
  2025-01-06 10:09   ` Masami Hiramatsu
  2025-01-05 12:48 ` [PATCH v2 6/6] tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos Masami Hiramatsu (Google)
  5 siblings, 1 reply; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:48 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Use __free() in trace_kprobe.c to cleanup code.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v2:
  - Instead of using no_free_ptr(), just assign NULL to the registered pointer.
---
 kernel/trace/trace_kprobe.c |   57 ++++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 31 deletions(-)

diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 4c3e316454a0..e1ae65f57bf9 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -8,6 +8,7 @@
 #define pr_fmt(fmt)	"trace_kprobe: " fmt
 
 #include <linux/bpf-cgroup.h>
+#include <linux/cleanup.h>
 #include <linux/security.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
@@ -257,6 +258,8 @@ static void free_trace_kprobe(struct trace_kprobe *tk)
 	}
 }
 
+DEFINE_FREE(trace_kprobe, struct trace_kprobe *, free_trace_kprobe(_T))
+
 /*
  * Allocate new trace_probe and initialize it (including kprobes).
  */
@@ -268,7 +271,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
 					     int maxactive,
 					     int nargs, bool is_return)
 {
-	struct trace_kprobe *tk;
+	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
 	int ret = -ENOMEM;
 
 	tk = kzalloc(struct_size(tk, tp.args, nargs), GFP_KERNEL);
@@ -277,12 +280,12 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
 
 	tk->nhit = alloc_percpu(unsigned long);
 	if (!tk->nhit)
-		goto error;
+		return ERR_PTR(ret);
 
 	if (symbol) {
 		tk->symbol = kstrdup(symbol, GFP_KERNEL);
 		if (!tk->symbol)
-			goto error;
+			return ERR_PTR(ret);
 		tk->rp.kp.symbol_name = tk->symbol;
 		tk->rp.kp.offset = offs;
 	} else
@@ -299,13 +302,10 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
 
 	ret = trace_probe_init(&tk->tp, event, group, false, nargs);
 	if (ret < 0)
-		goto error;
+		return ERR_PTR(ret);
 
 	dyn_event_init(&tk->devent, &trace_kprobe_ops);
-	return tk;
-error:
-	free_trace_kprobe(tk);
-	return ERR_PTR(ret);
+	return_ptr(tk);
 }
 
 static struct trace_kprobe *find_trace_kprobe(const char *event,
@@ -861,11 +861,12 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	 * Type of args:
 	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.
 	 */
-	struct trace_kprobe *tk = NULL;
+	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
 	int i, len, new_argc = 0, ret = 0;
 	bool is_return = false;
-	char *symbol = NULL, *tmp = NULL;
-	const char **new_argv = NULL;
+	char *symbol __free(kfree) = NULL;
+	char *tmp = NULL;
+	const char **new_argv __free(kfree) = NULL;
 	const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
 	enum probe_print_type ptype;
 	int maxactive = 0;
@@ -874,7 +875,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	char buf[MAX_EVENT_NAME_LEN];
 	char gbuf[MAX_EVENT_NAME_LEN];
 	char abuf[MAX_BTF_ARGS_LEN];
-	char *dbuf = NULL;
+	char *dbuf __free(kfree) = NULL;
 	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
 
 	switch (argv[0][0]) {
@@ -931,7 +932,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		/* Check whether uprobe event specified */
 		if (strchr(argv[1], '/') && strchr(argv[1], ':')) {
 			ret = -ECANCELED;
-			goto error;
+			goto out;
 		}
 		/* a symbol specified */
 		symbol = kstrdup(argv[1], GFP_KERNEL);
@@ -1035,7 +1036,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		ctx.offset = 0;
 		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
 		if (ret)
-			goto error;	/* This can be -ENOMEM */
+			goto out;	/* This can be -ENOMEM */
 	}
 	/* entry handler for kretprobe */
 	if (is_return && tk->tp.entry_arg) {
@@ -1046,7 +1047,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
 	ret = traceprobe_set_print_fmt(&tk->tp, ptype);
 	if (ret < 0)
-		goto error;
+		goto out;
 
 	ret = register_trace_kprobe(tk);
 	if (ret) {
@@ -1057,21 +1058,20 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 			trace_probe_log_err(0, BAD_PROBE_ADDR);
 		else if (ret != -ENOMEM && ret != -EEXIST)
 			trace_probe_log_err(0, FAIL_REG_PROBE);
-		goto error;
-	}
+	} else
+		/*
+		 * Here, 'tk' has been registered to the list successfully,
+		 * so we don't need to free it.
+		 */
+		tk = NULL;
 
 out:
 	traceprobe_finish_parse(&ctx);
 	trace_probe_log_clear();
-	kfree(new_argv);
-	kfree(symbol);
-	kfree(dbuf);
 	return ret;
 
 parse_error:
 	ret = -EINVAL;
-error:
-	free_trace_kprobe(tk);
 	goto out;
 }
 
@@ -1893,7 +1893,7 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
 			  bool is_return)
 {
 	enum probe_print_type ptype;
-	struct trace_kprobe *tk;
+	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
 	int ret;
 	char *event;
 
@@ -1924,19 +1924,14 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
 
 	ptype = trace_kprobe_is_return(tk) ?
 		PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
-	if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0) {
-		ret = -ENOMEM;
-		goto error;
-	}
+	if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0)
+		return ERR_PTR(-ENOMEM);
 
 	ret = __register_trace_kprobe(tk);
 	if (ret < 0)
-		goto error;
+		return ERR_PTR(ret);
 
 	return trace_probe_event_call(&tk->tp);
-error:
-	free_trace_kprobe(tk);
-	return ERR_PTR(ret);
 }
 
 void destroy_local_trace_kprobe(struct trace_event_call *event_call)


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v2 6/6] tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos
  2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
                   ` (4 preceding siblings ...)
  2025-01-05 12:48 ` [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup Masami Hiramatsu (Google)
@ 2025-01-05 12:48 ` Masami Hiramatsu (Google)
  5 siblings, 0 replies; 16+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-01-05 12:48 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra
  Cc: Anil S Keshavamurthy, Masami Hiramatsu, David S . Miller,
	Mathieu Desnoyers, Oleg Nesterov, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Simplify __trace_kprobe_create() by removing gotos.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 kernel/trace/trace_kprobe.c |   82 ++++++++++++++++++++++---------------------
 1 file changed, 41 insertions(+), 41 deletions(-)

diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index e1ae65f57bf9..b5c59c0f83cb 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -835,7 +835,8 @@ static int validate_probe_symbol(char *symbol)
 static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
 				      struct pt_regs *regs);
 
-static int __trace_kprobe_create(int argc, const char *argv[])
+static int ___trace_kprobe_create(int argc, const char *argv[],
+				  struct traceprobe_parse_context *ctx)
 {
 	/*
 	 * Argument syntax:
@@ -876,7 +877,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	char gbuf[MAX_EVENT_NAME_LEN];
 	char abuf[MAX_BTF_ARGS_LEN];
 	char *dbuf __free(kfree) = NULL;
-	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
 
 	switch (argv[0][0]) {
 	case 'r':
@@ -890,8 +890,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	if (argc < 2)
 		return -ECANCELED;
 
-	trace_probe_log_init("trace_kprobe", argc, argv);
-
 	event = strchr(&argv[0][1], ':');
 	if (event)
 		event++;
@@ -899,7 +897,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	if (isdigit(argv[0][1])) {
 		if (!is_return) {
 			trace_probe_log_err(1, BAD_MAXACT_TYPE);
-			goto parse_error;
+			return -EINVAL;
 		}
 		if (event)
 			len = event - &argv[0][1] - 1;
@@ -907,21 +905,21 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 			len = strlen(&argv[0][1]);
 		if (len > MAX_EVENT_NAME_LEN - 1) {
 			trace_probe_log_err(1, BAD_MAXACT);
-			goto parse_error;
+			return -EINVAL;
 		}
 		memcpy(buf, &argv[0][1], len);
 		buf[len] = '\0';
 		ret = kstrtouint(buf, 0, &maxactive);
 		if (ret || !maxactive) {
 			trace_probe_log_err(1, BAD_MAXACT);
-			goto parse_error;
+			return -EINVAL;
 		}
 		/* kretprobes instances are iterated over via a list. The
 		 * maximum should stay reasonable.
 		 */
 		if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
 			trace_probe_log_err(1, MAXACT_TOO_BIG);
-			goto parse_error;
+			return -EINVAL;
 		}
 	}
 
@@ -930,16 +928,13 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
 		trace_probe_log_set_index(1);
 		/* Check whether uprobe event specified */
-		if (strchr(argv[1], '/') && strchr(argv[1], ':')) {
-			ret = -ECANCELED;
-			goto out;
-		}
+		if (strchr(argv[1], '/') && strchr(argv[1], ':'))
+			return -ECANCELED;
+
 		/* a symbol specified */
 		symbol = kstrdup(argv[1], GFP_KERNEL);
-		if (!symbol) {
-			ret = -ENOMEM;
-			goto error;
-		}
+		if (!symbol)
+			return -ENOMEM;
 
 		tmp = strchr(symbol, '%');
 		if (tmp) {
@@ -948,7 +943,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 				is_return = true;
 			} else {
 				trace_probe_log_err(tmp - symbol, BAD_ADDR_SUFFIX);
-				goto parse_error;
+				return -EINVAL;
 			}
 		}
 
@@ -956,7 +951,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		ret = traceprobe_split_symbol_offset(symbol, &offset);
 		if (ret || offset < 0 || offset > UINT_MAX) {
 			trace_probe_log_err(0, BAD_PROBE_ADDR);
-			goto parse_error;
+			return -EINVAL;
 		}
 		ret = validate_probe_symbol(symbol);
 		if (ret) {
@@ -964,17 +959,17 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 				trace_probe_log_err(0, NON_UNIQ_SYMBOL);
 			else
 				trace_probe_log_err(0, BAD_PROBE_ADDR);
-			goto parse_error;
+			return -EINVAL;
 		}
 		if (is_return)
-			ctx.flags |= TPARG_FL_RETURN;
+			ctx->flags |= TPARG_FL_RETURN;
 		ret = kprobe_on_func_entry(NULL, symbol, offset);
 		if (ret == 0 && !is_return)
-			ctx.flags |= TPARG_FL_FENTRY;
+			ctx->flags |= TPARG_FL_FENTRY;
 		/* Defer the ENOENT case until register kprobe */
 		if (ret == -EINVAL && is_return) {
 			trace_probe_log_err(0, BAD_RETPROBE);
-			goto parse_error;
+			return -EINVAL;
 		}
 	}
 
@@ -983,7 +978,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		ret = traceprobe_parse_event_name(&event, &group, gbuf,
 						  event - argv[0]);
 		if (ret)
-			goto parse_error;
+			return ret;
 	}
 
 	if (!event) {
@@ -999,26 +994,24 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	}
 
 	argc -= 2; argv += 2;
-	ctx.funcname = symbol;
+	ctx->funcname = symbol;
 	new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
-					       abuf, MAX_BTF_ARGS_LEN, &ctx);
+					       abuf, MAX_BTF_ARGS_LEN, ctx);
 	if (IS_ERR(new_argv)) {
 		ret = PTR_ERR(new_argv);
 		new_argv = NULL;
-		goto out;
+		return ret;
 	}
 	if (new_argv) {
 		argc = new_argc;
 		argv = new_argv;
 	}
-	if (argc > MAX_TRACE_ARGS) {
-		ret = -E2BIG;
-		goto out;
-	}
+	if (argc > MAX_TRACE_ARGS)
+		return -E2BIG;
 
 	ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
 	if (ret)
-		goto out;
+		return ret;
 
 	/* setup a probe */
 	tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
@@ -1027,16 +1020,16 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		ret = PTR_ERR(tk);
 		/* This must return -ENOMEM, else there is a bug */
 		WARN_ON_ONCE(ret != -ENOMEM);
-		goto out;	/* We know tk is not allocated */
+		return ret;	/* We know tk is not allocated */
 	}
 
 	/* parse arguments */
 	for (i = 0; i < argc; i++) {
 		trace_probe_log_set_index(i + 2);
-		ctx.offset = 0;
-		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
+		ctx->offset = 0;
+		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], ctx);
 		if (ret)
-			goto out;	/* This can be -ENOMEM */
+			return ret;	/* This can be -ENOMEM */
 	}
 	/* entry handler for kretprobe */
 	if (is_return && tk->tp.entry_arg) {
@@ -1047,7 +1040,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 	ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
 	ret = traceprobe_set_print_fmt(&tk->tp, ptype);
 	if (ret < 0)
-		goto out;
+		return ret;
 
 	ret = register_trace_kprobe(tk);
 	if (ret) {
@@ -1065,14 +1058,21 @@ static int __trace_kprobe_create(int argc, const char *argv[])
 		 */
 		tk = NULL;
 
-out:
+	return ret;
+}
+
+static int __trace_kprobe_create(int argc, const char *argv[])
+{
+	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
+	int ret;
+
+	trace_probe_log_init("trace_kprobe", argc, argv);
+
+	ret = ___trace_kprobe_create(argc, argv, &ctx);
+
 	traceprobe_finish_parse(&ctx);
 	trace_probe_log_clear();
 	return ret;
-
-parse_error:
-	ret = -EINVAL;
-	goto out;
 }
 
 static int trace_kprobe_create(const char *raw_command)


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-05 12:47 ` [PATCH v2 2/6] Provide __free(argv) for argv_split() users Masami Hiramatsu (Google)
@ 2025-01-05 14:14   ` Oleg Nesterov
  2025-01-06 10:26     ` Peter Zijlstra
  2025-01-06 12:19     ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Masami Hiramatsu
  0 siblings, 2 replies; 16+ messages in thread
From: Oleg Nesterov @ 2025-01-05 14:14 UTC (permalink / raw)
  To: Masami Hiramatsu (Google), Peter Zijlstra
  Cc: Steven Rostedt, Anil S Keshavamurthy, David S . Miller,
	Mathieu Desnoyers, Tzvetomir Stoyanov, Naveen N Rao,
	Josh Poimboeuf, Jason Baron, Ard Biesheuvel, linux-kernel,
	linux-trace-kernel

Masami,

Sorry for abusing this thread. Your patches look fine to me, it is not
that I suggest to change them. I will use your patch as an example for
off-topic discussion.

On 01/05, Masami Hiramatsu (Google) wrote:
>
> +DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))

(IS_ERR looks unneeded but this is cosmetic).

OK, so it can be used as

	void func(void)
	{
		char **argv __free(argv) = argv_split(...);
		do_something(argv);
		return;
	}

And I cry every time when I read the code like this ;)

Because, to understand this code, I need to do the "nontrivial" grep to find
"DEFINE_FREE(argv,".

Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
should add another #define? I mean something like


	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
	#define __FREE_ARGV	__free(argv)
	
	void func(void)
	{
		char **argv __FREE_ARGV = argv_split(...);
		do_something(argv);
		return;
	}

This way I can press Ctrl-] and see what the cleanup code actually does.
Can save a second or two. Important when you try to read the code you are
not familiar with.

Same for DEFINE_CLASS. For example,

	int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
	{
		CLASS(fd, f)(fd);

		if (fd_empty(f))
			return -EBADF;

		return vfs_fchown(fd_file(f), user, group);
	}

If you are not familiar with this code, it looks mysterious until you find
DEFINE_CLASS(fd, ...) in include/linux/file.h.

Oleg.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup
  2025-01-05 12:48 ` [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup Masami Hiramatsu (Google)
@ 2025-01-06 10:09   ` Masami Hiramatsu
  0 siblings, 0 replies; 16+ messages in thread
From: Masami Hiramatsu @ 2025-01-06 10:09 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Peter Zijlstra, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Oleg Nesterov,
	Tzvetomir Stoyanov, Naveen N Rao, Josh Poimboeuf, Jason Baron,
	Ard Biesheuvel, linux-kernel, linux-trace-kernel

On Sun,  5 Jan 2025 21:48:29 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Use __free() in trace_kprobe.c to cleanup code.
> 
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>  Changes in v2:
>   - Instead of using no_free_ptr(), just assign NULL to the registered pointer.
> ---
>  kernel/trace/trace_kprobe.c |   57 ++++++++++++++++++++-----------------------
>  1 file changed, 26 insertions(+), 31 deletions(-)
> 
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index 4c3e316454a0..e1ae65f57bf9 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -8,6 +8,7 @@
>  #define pr_fmt(fmt)	"trace_kprobe: " fmt
>  
>  #include <linux/bpf-cgroup.h>
> +#include <linux/cleanup.h>
>  #include <linux/security.h>
>  #include <linux/module.h>
>  #include <linux/uaccess.h>
> @@ -257,6 +258,8 @@ static void free_trace_kprobe(struct trace_kprobe *tk)
>  	}
>  }
>  
> +DEFINE_FREE(trace_kprobe, struct trace_kprobe *, free_trace_kprobe(_T))

Oops, this also need to check !IS_ERR_OR_NULL(_T) since free_trace_kprobe()
only checks the pointer != NULL.

Thanks,

> +
>  /*
>   * Allocate new trace_probe and initialize it (including kprobes).
>   */
> @@ -268,7 +271,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
>  					     int maxactive,
>  					     int nargs, bool is_return)
>  {
> -	struct trace_kprobe *tk;
> +	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
>  	int ret = -ENOMEM;
>  
>  	tk = kzalloc(struct_size(tk, tp.args, nargs), GFP_KERNEL);
> @@ -277,12 +280,12 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
>  
>  	tk->nhit = alloc_percpu(unsigned long);
>  	if (!tk->nhit)
> -		goto error;
> +		return ERR_PTR(ret);
>  
>  	if (symbol) {
>  		tk->symbol = kstrdup(symbol, GFP_KERNEL);
>  		if (!tk->symbol)
> -			goto error;
> +			return ERR_PTR(ret);
>  		tk->rp.kp.symbol_name = tk->symbol;
>  		tk->rp.kp.offset = offs;
>  	} else
> @@ -299,13 +302,10 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
>  
>  	ret = trace_probe_init(&tk->tp, event, group, false, nargs);
>  	if (ret < 0)
> -		goto error;
> +		return ERR_PTR(ret);
>  
>  	dyn_event_init(&tk->devent, &trace_kprobe_ops);
> -	return tk;
> -error:
> -	free_trace_kprobe(tk);
> -	return ERR_PTR(ret);
> +	return_ptr(tk);
>  }
>  
>  static struct trace_kprobe *find_trace_kprobe(const char *event,
> @@ -861,11 +861,12 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  	 * Type of args:
>  	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.
>  	 */
> -	struct trace_kprobe *tk = NULL;
> +	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
>  	int i, len, new_argc = 0, ret = 0;
>  	bool is_return = false;
> -	char *symbol = NULL, *tmp = NULL;
> -	const char **new_argv = NULL;
> +	char *symbol __free(kfree) = NULL;
> +	char *tmp = NULL;
> +	const char **new_argv __free(kfree) = NULL;
>  	const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
>  	enum probe_print_type ptype;
>  	int maxactive = 0;
> @@ -874,7 +875,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  	char buf[MAX_EVENT_NAME_LEN];
>  	char gbuf[MAX_EVENT_NAME_LEN];
>  	char abuf[MAX_BTF_ARGS_LEN];
> -	char *dbuf = NULL;
> +	char *dbuf __free(kfree) = NULL;
>  	struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
>  
>  	switch (argv[0][0]) {
> @@ -931,7 +932,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  		/* Check whether uprobe event specified */
>  		if (strchr(argv[1], '/') && strchr(argv[1], ':')) {
>  			ret = -ECANCELED;
> -			goto error;
> +			goto out;
>  		}
>  		/* a symbol specified */
>  		symbol = kstrdup(argv[1], GFP_KERNEL);
> @@ -1035,7 +1036,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  		ctx.offset = 0;
>  		ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
>  		if (ret)
> -			goto error;	/* This can be -ENOMEM */
> +			goto out;	/* This can be -ENOMEM */
>  	}
>  	/* entry handler for kretprobe */
>  	if (is_return && tk->tp.entry_arg) {
> @@ -1046,7 +1047,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  	ptype = is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
>  	ret = traceprobe_set_print_fmt(&tk->tp, ptype);
>  	if (ret < 0)
> -		goto error;
> +		goto out;
>  
>  	ret = register_trace_kprobe(tk);
>  	if (ret) {
> @@ -1057,21 +1058,20 @@ static int __trace_kprobe_create(int argc, const char *argv[])
>  			trace_probe_log_err(0, BAD_PROBE_ADDR);
>  		else if (ret != -ENOMEM && ret != -EEXIST)
>  			trace_probe_log_err(0, FAIL_REG_PROBE);
> -		goto error;
> -	}
> +	} else
> +		/*
> +		 * Here, 'tk' has been registered to the list successfully,
> +		 * so we don't need to free it.
> +		 */
> +		tk = NULL;
>  
>  out:
>  	traceprobe_finish_parse(&ctx);
>  	trace_probe_log_clear();
> -	kfree(new_argv);
> -	kfree(symbol);
> -	kfree(dbuf);
>  	return ret;
>  
>  parse_error:
>  	ret = -EINVAL;
> -error:
> -	free_trace_kprobe(tk);
>  	goto out;
>  }
>  
> @@ -1893,7 +1893,7 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
>  			  bool is_return)
>  {
>  	enum probe_print_type ptype;
> -	struct trace_kprobe *tk;
> +	struct trace_kprobe *tk __free(trace_kprobe) = NULL;
>  	int ret;
>  	char *event;
>  
> @@ -1924,19 +1924,14 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
>  
>  	ptype = trace_kprobe_is_return(tk) ?
>  		PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
> -	if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0) {
> -		ret = -ENOMEM;
> -		goto error;
> -	}
> +	if (traceprobe_set_print_fmt(&tk->tp, ptype) < 0)
> +		return ERR_PTR(-ENOMEM);
>  
>  	ret = __register_trace_kprobe(tk);
>  	if (ret < 0)
> -		goto error;
> +		return ERR_PTR(ret);
>  
>  	return trace_probe_event_call(&tk->tp);
> -error:
> -	free_trace_kprobe(tk);
> -	return ERR_PTR(ret);
>  }
>  
>  void destroy_local_trace_kprobe(struct trace_event_call *event_call)
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-05 14:14   ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Oleg Nesterov
@ 2025-01-06 10:26     ` Peter Zijlstra
  2025-01-06 11:18       ` Peter Zijlstra
                         ` (2 more replies)
  2025-01-06 12:19     ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Masami Hiramatsu
  1 sibling, 3 replies; 16+ messages in thread
From: Peter Zijlstra @ 2025-01-06 10:26 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Masami Hiramatsu (Google), Steven Rostedt, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

On Sun, Jan 05, 2025 at 03:14:22PM +0100, Oleg Nesterov wrote:

> OK, so it can be used as
> 
> 	void func(void)
> 	{
> 		char **argv __free(argv) = argv_split(...);
> 		do_something(argv);
> 		return;
> 	}
> 
> And I cry every time when I read the code like this ;)
> 
> Because, to understand this code, I need to do the "nontrivial" grep to find
> "DEFINE_FREE(argv,".
> 
> Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
> should add another #define? I mean something like
> 
> 
> 	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> 	#define __FREE_ARGV	__free(argv)
> 	
> 	void func(void)
> 	{
> 		char **argv __FREE_ARGV = argv_split(...);
> 		do_something(argv);
> 		return;
> 	}
> 
> This way I can press Ctrl-] and see what the cleanup code actually does.
> Can save a second or two. Important when you try to read the code you are
> not familiar with.

Right, so I've been playing with neovim and clangd (lsp), and I'm very
disappointed to have to tell you that that also doesn't get it :-(

One thing we can and should do is something like:

diff --git a/scripts/tags.sh b/scripts/tags.sh
index b21236377998..f01d694abe65 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -212,6 +212,8 @@ regex_c=(
 	'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
 	'/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
 	'/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
+	'/^\<DEFINE_FREE(\([[:alnum:]_]\+\)/cleanup_\1/'
+	'/^\<DEFINE_CLASS(\([[:alnum:]_]\+\)/class_\1/'
 )
 regex_kconfig=(
 	'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'

That should be able to let you do: ':ts cleanup_argv'

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-06 10:26     ` Peter Zijlstra
@ 2025-01-06 11:18       ` Peter Zijlstra
  2025-01-06 14:44       ` Oleg Nesterov
  2025-01-11 13:21       ` [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives tip-bot2 for Peter Zijlstra
  2 siblings, 0 replies; 16+ messages in thread
From: Peter Zijlstra @ 2025-01-06 11:18 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Masami Hiramatsu (Google), Steven Rostedt, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

On Mon, Jan 06, 2025 at 11:26:48AM +0100, Peter Zijlstra wrote:
> On Sun, Jan 05, 2025 at 03:14:22PM +0100, Oleg Nesterov wrote:
> 
> > OK, so it can be used as
> > 
> > 	void func(void)
> > 	{
> > 		char **argv __free(argv) = argv_split(...);
> > 		do_something(argv);
> > 		return;
> > 	}
> > 
> > And I cry every time when I read the code like this ;)
> > 
> > Because, to understand this code, I need to do the "nontrivial" grep to find
> > "DEFINE_FREE(argv,".
> > 
> > Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
> > should add another #define? I mean something like
> > 
> > 
> > 	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> > 	#define __FREE_ARGV	__free(argv)
> > 	
> > 	void func(void)
> > 	{
> > 		char **argv __FREE_ARGV = argv_split(...);
> > 		do_something(argv);
> > 		return;
> > 	}
> > 
> > This way I can press Ctrl-] and see what the cleanup code actually does.
> > Can save a second or two. Important when you try to read the code you are
> > not familiar with.
> 
> Right, so I've been playing with neovim and clangd (lsp), and I'm very
> disappointed to have to tell you that that also doesn't get it :-(
> 
> One thing we can and should do is something like:
> 
> diff --git a/scripts/tags.sh b/scripts/tags.sh
> index b21236377998..f01d694abe65 100755
> --- a/scripts/tags.sh
> +++ b/scripts/tags.sh
> @@ -212,6 +212,8 @@ regex_c=(
>  	'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
>  	'/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
>  	'/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
> +	'/^\<DEFINE_FREE(\([[:alnum:]_]\+\)/cleanup_\1/'
> +	'/^\<DEFINE_CLASS(\([[:alnum:]_]\+\)/class_\1/'
	/^\<EXTEND_CLASS(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]]\+\)/class_\1\2/'
	/^\<DEFINE_GUARD(\([[:alnum:]_]\+\)/class_\1/'
	/^\<DEFINE_GUARD_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]]\+\)/class_\1\2/'
	/^\<DEFINE_LOCK_GUARD_[[:digit:]](\([[:alnum:]_]\+\)/class_\1/'
	/^\<DEFINE_LOCK_GUARD_[[:digit:]]_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]]\+\)/class_\1\2/'

I suppose... not tested these

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-05 14:14   ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Oleg Nesterov
  2025-01-06 10:26     ` Peter Zijlstra
@ 2025-01-06 12:19     ` Masami Hiramatsu
  2025-01-06 14:33       ` Oleg Nesterov
  1 sibling, 1 reply; 16+ messages in thread
From: Masami Hiramatsu @ 2025-01-06 12:19 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Peter Zijlstra, Steven Rostedt, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

On Sun, 5 Jan 2025 15:14:22 +0100
Oleg Nesterov <oleg@redhat.com> wrote:

> Masami,
> 
> Sorry for abusing this thread. Your patches look fine to me, it is not
> that I suggest to change them. I will use your patch as an example for
> off-topic discussion.
> 
> On 01/05, Masami Hiramatsu (Google) wrote:
> >
> > +DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> 
> (IS_ERR looks unneeded but this is cosmetic).
> 
> OK, so it can be used as
> 
> 	void func(void)
> 	{
> 		char **argv __free(argv) = argv_split(...);
> 		do_something(argv);
> 		return;
> 	}
> 
> And I cry every time when I read the code like this ;)
> 
> Because, to understand this code, I need to do the "nontrivial" grep to find
> "DEFINE_FREE(argv,".
> 
> Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
> should add another #define? I mean something like
> 
> 
> 	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> 	#define __FREE_ARGV	__free(argv)
> 	
> 	void func(void)
> 	{
> 		char **argv __FREE_ARGV = argv_split(...);
> 		do_something(argv);
> 		return;
> 	}
> 
> This way I can press Ctrl-] and see what the cleanup code actually does.
> Can save a second or two. Important when you try to read the code you are
> not familiar with.

That sounds lile a problem of your tool. Do you really need to find the
DEFINE_FREE() or do you think "__free(argv)" is too generic name?
If it is latter, we can make it "__free(argv_free) so that it is more
obvious to call argv_free()?

> 
> Same for DEFINE_CLASS. For example,
> 
> 	int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
> 	{
> 		CLASS(fd, f)(fd);
> 
> 		if (fd_empty(f))
> 			return -EBADF;
> 
> 		return vfs_fchown(fd_file(f), user, group);
> 	}
> 
> If you are not familiar with this code, it looks mysterious until you find
> DEFINE_CLASS(fd, ...) in include/linux/file.h.

DEFINE_CLASS() is somewhat mysterious to me too :) But if I understand
correctly, it is for intermediate macro for implementing guard().

Whether we like it or not, cleanup.h has been introduced, and it will be
more popular. What we need is a document about cleanup.h which includes
better naming conventions for its label.

BTW, I agree that 'argv' was too simple. Basically the label name of
DEFINE_FREE() is better to be a function name for free.
Let me fix that.

Thank you,

-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-06 12:19     ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Masami Hiramatsu
@ 2025-01-06 14:33       ` Oleg Nesterov
  0 siblings, 0 replies; 16+ messages in thread
From: Oleg Nesterov @ 2025-01-06 14:33 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Peter Zijlstra, Steven Rostedt, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

On 01/06, Masami Hiramatsu wrote:
>
> On Sun, 5 Jan 2025 15:14:22 +0100
> Oleg Nesterov <oleg@redhat.com> wrote:
>
> > Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
> > should add another #define? I mean something like
> >
> >
> > 	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> > 	#define __FREE_ARGV	__free(argv)
> >
> > 	void func(void)
> > 	{
> > 		char **argv __FREE_ARGV = argv_split(...);
> > 		do_something(argv);
> > 		return;
> > 	}
> >
> > This way I can press Ctrl-] and see what the cleanup code actually does.
> > Can save a second or two. Important when you try to read the code you are
> > not familiar with.
>
> That sounds lile a problem of your tool. Do you really need to find the
> DEFINE_FREE()

Yes, ":tag __free_argv" wont work. it is defined by DEFINE_FREE(argv) above.
I need to find this DEFINE_FREE(argv) to see what __free_argv() actually does.

> > Same for DEFINE_CLASS. For example,
> >
> > 	int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
> > 	{
> > 		CLASS(fd, f)(fd);
> >
> > 		if (fd_empty(f))
> > 			return -EBADF;
> >
> > 		return vfs_fchown(fd_file(f), user, group);
> > 	}
> >
> > If you are not familiar with this code, it looks mysterious until you find
> > DEFINE_CLASS(fd, ...) in include/linux/file.h.
>
> DEFINE_CLASS() is somewhat mysterious to me too :) But if I understand
> correctly, it is for intermediate macro for implementing guard().

Well, in this case you just need to find

	DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)

in include/linux/file.h, after that the code is clear.

> BTW, I agree that 'argv' was too simple. Basically the label name of
> DEFINE_FREE() is better to be a function name for free.
> Let me fix that.

Up to you, but __free(argv) looks good to me.

Oleg.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users)
  2025-01-06 10:26     ` Peter Zijlstra
  2025-01-06 11:18       ` Peter Zijlstra
@ 2025-01-06 14:44       ` Oleg Nesterov
  2025-01-11 13:21       ` [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives tip-bot2 for Peter Zijlstra
  2 siblings, 0 replies; 16+ messages in thread
From: Oleg Nesterov @ 2025-01-06 14:44 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Masami Hiramatsu (Google), Steven Rostedt, Anil S Keshavamurthy,
	David S . Miller, Mathieu Desnoyers, Tzvetomir Stoyanov,
	Naveen N Rao, Josh Poimboeuf, Jason Baron, Ard Biesheuvel,
	linux-kernel, linux-trace-kernel

On 01/06, Peter Zijlstra wrote:
>
> On Sun, Jan 05, 2025 at 03:14:22PM +0100, Oleg Nesterov wrote:
>
> > Perhaps we can establish a simple rule that every DEFINE_FREE() or DEFINE_CLASS()
> > should add another #define? I mean something like
> >
> > 	DEFINE_FREE(argv, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
> > 	#define __FREE_ARGV	__free(argv)
> >
> > 	void func(void)
> > 	{
> > 		char **argv __FREE_ARGV = argv_split(...);
> > 		do_something(argv);
> > 		return;
> > 	}
> >
> > This way I can press Ctrl-] and see what the cleanup code actually does.
> > Can save a second or two. Important when you try to read the code you are
> > not familiar with.
>
> Right, so I've been playing with neovim and clangd (lsp), and I'm very
> disappointed to have to tell you that that also doesn't get it :-(
>
> One thing we can and should do is something like:
>
> diff --git a/scripts/tags.sh b/scripts/tags.sh
> index b21236377998..f01d694abe65 100755
> --- a/scripts/tags.sh
> +++ b/scripts/tags.sh
> @@ -212,6 +212,8 @@ regex_c=(
>  	'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
>  	'/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
>  	'/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
> +	'/^\<DEFINE_FREE(\([[:alnum:]_]\+\)/cleanup_\1/'
> +	'/^\<DEFINE_CLASS(\([[:alnum:]_]\+\)/class_\1/'

Yes, thanks ;)

Ctrl-] still won't work, but at least ":ta cleanup_argv" will do.

Thanks,

Oleg.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives
  2025-01-06 10:26     ` Peter Zijlstra
  2025-01-06 11:18       ` Peter Zijlstra
  2025-01-06 14:44       ` Oleg Nesterov
@ 2025-01-11 13:21       ` tip-bot2 for Peter Zijlstra
  2025-01-14 21:29         ` Oleg Nesterov
  2 siblings, 1 reply; 16+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2025-01-11 13:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Oleg Nesterov, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     a937f384c9da493e526ad896ef4e8054526d2941
Gitweb:        https://git.kernel.org/tip/a937f384c9da493e526ad896ef4e8054526d2941
Author:        Peter Zijlstra <peterz@infradead.org>
AuthorDate:    Mon, 06 Jan 2025 11:26:48 +01:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 10 Jan 2025 18:16:48 +01:00

cleanup, tags: Create tags for the cleanup primitives

Oleg reported that it is hard to find the definition of things like:
__free(argv) without having to do 'git grep "DEFINE_FREE(argv,"'.

Add tag generation for the various macros in cleanup.h.

Notably 'DEFINE_FREE(argv, ...)' will now generate a 'cleanup_argv'
tag, while all the others, eg. 'DEFINE_GUARD(mutex, ...)' will
generate 'class_mutex' like tags.

Reported-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20250106102647.GB20870@noisy.programming.kicks-ass.net
---
 scripts/tags.sh | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/scripts/tags.sh b/scripts/tags.sh
index b212363..7939aea 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -212,6 +212,13 @@ regex_c=(
 	'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
 	'/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
 	'/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
+	'/^\<DEFINE_FREE(\([[:alnum:]_]\+\)/cleanup_\1/'
+	'/^\<DEFINE_CLASS(\([[:alnum:]_]\+\)/class_\1/'
+	'/^\<EXTEND_CLASS(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
+	'/^\<DEFINE_GUARD(\([[:alnum:]_]\+\)/class_\1/'
+	'/^\<DEFINE_GUARD_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
+	'/^\<DEFINE_LOCK_GUARD_[[:digit:]](\([[:alnum:]_]\+\)/class_\1/'
+	'/^\<DEFINE_LOCK_GUARD_[[:digit:]]_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
 )
 regex_kconfig=(
 	'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives
  2025-01-11 13:21       ` [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives tip-bot2 for Peter Zijlstra
@ 2025-01-14 21:29         ` Oleg Nesterov
  0 siblings, 0 replies; 16+ messages in thread
From: Oleg Nesterov @ 2025-01-14 21:29 UTC (permalink / raw)
  To: tip-bot2 for Peter Zijlstra
  Cc: linux-tip-commits, Peter Zijlstra (Intel), x86, linux-kernel

On 01/11, tip-bot2 for Peter Zijlstra wrote:
>
> --- a/scripts/tags.sh
> +++ b/scripts/tags.sh
> @@ -212,6 +212,13 @@ regex_c=(
>  	'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
>  	'/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
>  	'/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
> +	'/^\<DEFINE_FREE(\([[:alnum:]_]\+\)/cleanup_\1/'
> +	'/^\<DEFINE_CLASS(\([[:alnum:]_]\+\)/class_\1/'
> +	'/^\<EXTEND_CLASS(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
> +	'/^\<DEFINE_GUARD(\([[:alnum:]_]\+\)/class_\1/'
> +	'/^\<DEFINE_GUARD_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
> +	'/^\<DEFINE_LOCK_GUARD_[[:digit:]](\([[:alnum:]_]\+\)/class_\1/'
> +	'/^\<DEFINE_LOCK_GUARD_[[:digit:]]_COND(\([[:alnum:]_]\+\),[[:space:]]*\([[:alnum:]_]\+\)/class_\1\2/'
>  )

Thanks ;)

I don't use scripts/tags.sh, but I will add these changes to my personal
scripts.

Oleg.


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2025-01-14 21:30 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-05 12:47 [PATCH v2 0/6] tracing/kprobes: Cleanup with guard and __free Masami Hiramatsu (Google)
2025-01-05 12:47 ` [PATCH v2 1/6] tracing/kprobes: Fix to free objects when failed to copy a symbol Masami Hiramatsu (Google)
2025-01-05 12:47 ` [PATCH v2 2/6] Provide __free(argv) for argv_split() users Masami Hiramatsu (Google)
2025-01-05 14:14   ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Oleg Nesterov
2025-01-06 10:26     ` Peter Zijlstra
2025-01-06 11:18       ` Peter Zijlstra
2025-01-06 14:44       ` Oleg Nesterov
2025-01-11 13:21       ` [tip: locking/core] cleanup, tags: Create tags for the cleanup primitives tip-bot2 for Peter Zijlstra
2025-01-14 21:29         ` Oleg Nesterov
2025-01-06 12:19     ` DEFINE_FREE/CLASS && code readability (Was: [PATCH v2 2/6] Provide __free(argv) for argv_split() users) Masami Hiramatsu
2025-01-06 14:33       ` Oleg Nesterov
2025-01-05 12:48 ` [PATCH v2 3/6] tracing: Use __free() for argv in dynevent Masami Hiramatsu (Google)
2025-01-05 12:48 ` [PATCH v2 4/6] tracing: Use __free() in trace_probe for cleanup Masami Hiramatsu (Google)
2025-01-05 12:48 ` [PATCH v2 5/6] tracing: Use __free() for kprobe events to cleanup Masami Hiramatsu (Google)
2025-01-06 10:09   ` Masami Hiramatsu
2025-01-05 12:48 ` [PATCH v2 6/6] tracing/kprobes: Simplify __trace_kprobe_create() by removing gotos Masami Hiramatsu (Google)

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.