tracing: Adopt __free() and guard() for trace_fprobe.c

Adopt __free() and guard() for trace_fprobe.c to remove gotos.

Link: https://lore.kernel.org/173708043449.319651.12242878905778792182.stgit@mhiramat.roam.corp.google.com
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
Masami Hiramatsu (Google) 2025-01-17 11:20:34 +09:00 committed by Steven Rostedt (Google)
parent 4f7caaa2f9
commit 8275637215

View file

@ -416,6 +416,9 @@ static void free_trace_fprobe(struct trace_fprobe *tf)
} }
} }
/* Since alloc_trace_fprobe() can return error, check the pointer is ERR too. */
DEFINE_FREE(free_trace_fprobe, struct trace_fprobe *, if (!IS_ERR_OR_NULL(_T)) free_trace_fprobe(_T))
/* /*
* Allocate new trace_probe and initialize it (including fprobe). * Allocate new trace_probe and initialize it (including fprobe).
*/ */
@ -426,7 +429,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
struct module *mod, struct module *mod,
int nargs, bool is_return) int nargs, bool is_return)
{ {
struct trace_fprobe *tf; struct trace_fprobe *tf __free(free_trace_fprobe) = NULL;
int ret = -ENOMEM; int ret = -ENOMEM;
tf = kzalloc(struct_size(tf, tp.args, nargs), GFP_KERNEL); tf = kzalloc(struct_size(tf, tp.args, nargs), GFP_KERNEL);
@ -435,7 +438,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
tf->symbol = kstrdup(symbol, GFP_KERNEL); tf->symbol = kstrdup(symbol, GFP_KERNEL);
if (!tf->symbol) if (!tf->symbol)
goto error; return ERR_PTR(-ENOMEM);
if (is_return) if (is_return)
tf->fp.exit_handler = fexit_dispatcher; tf->fp.exit_handler = fexit_dispatcher;
@ -447,13 +450,10 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
ret = trace_probe_init(&tf->tp, event, group, false, nargs); ret = trace_probe_init(&tf->tp, event, group, false, nargs);
if (ret < 0) if (ret < 0)
goto error; return ERR_PTR(ret);
dyn_event_init(&tf->devent, &trace_fprobe_ops); dyn_event_init(&tf->devent, &trace_fprobe_ops);
return tf; return_ptr(tf);
error:
free_trace_fprobe(tf);
return ERR_PTR(ret);
} }
static struct trace_fprobe *find_trace_fprobe(const char *event, static struct trace_fprobe *find_trace_fprobe(const char *event,
@ -880,14 +880,12 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
struct trace_fprobe *old_tf; struct trace_fprobe *old_tf;
int ret; int ret;
mutex_lock(&event_mutex); guard(mutex)(&event_mutex);
old_tf = find_trace_fprobe(trace_probe_name(&tf->tp), old_tf = find_trace_fprobe(trace_probe_name(&tf->tp),
trace_probe_group_name(&tf->tp)); trace_probe_group_name(&tf->tp));
if (old_tf) { if (old_tf)
ret = append_trace_fprobe(tf, old_tf); return append_trace_fprobe(tf, old_tf);
goto end;
}
/* Register new event */ /* Register new event */
ret = register_fprobe_event(tf); ret = register_fprobe_event(tf);
@ -897,7 +895,7 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
trace_probe_log_err(0, EVENT_EXIST); trace_probe_log_err(0, EVENT_EXIST);
} else } else
pr_warn("Failed to register probe event(%d)\n", ret); pr_warn("Failed to register probe event(%d)\n", ret);
goto end; return ret;
} }
/* Register fprobe */ /* Register fprobe */
@ -907,8 +905,6 @@ static int register_trace_fprobe(struct trace_fprobe *tf)
else else
dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp)); dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp));
end:
mutex_unlock(&event_mutex);
return ret; return ret;
} }
@ -1069,7 +1065,10 @@ static int parse_symbol_and_return(int argc, const char *argv[],
return 0; return 0;
} }
static int __trace_fprobe_create(int argc, const char *argv[]) DEFINE_FREE(module_put, struct module *, if (_T) module_put(_T))
static int trace_fprobe_create_internal(int argc, const char *argv[],
struct traceprobe_parse_context *ctx)
{ {
/* /*
* Argument syntax: * Argument syntax:
@ -1095,23 +1094,20 @@ static int __trace_fprobe_create(int argc, const char *argv[])
* Type of args: * Type of args:
* FETCHARG:TYPE : use TYPE instead of unsigned long. * FETCHARG:TYPE : use TYPE instead of unsigned long.
*/ */
struct trace_fprobe *tf = NULL; struct trace_fprobe *tf __free(free_trace_fprobe) = NULL;
int i, new_argc = 0, ret = 0; int i, new_argc = 0, ret = 0;
bool is_return = false; bool is_return = false;
char *symbol = NULL; char *symbol __free(kfree) = NULL;
const char *event = NULL, *group = FPROBE_EVENT_SYSTEM; const char *event = NULL, *group = FPROBE_EVENT_SYSTEM;
const char **new_argv = NULL; const char **new_argv __free(kfree) = NULL;
char buf[MAX_EVENT_NAME_LEN]; char buf[MAX_EVENT_NAME_LEN];
char gbuf[MAX_EVENT_NAME_LEN]; char gbuf[MAX_EVENT_NAME_LEN];
char sbuf[KSYM_NAME_LEN]; char sbuf[KSYM_NAME_LEN];
char abuf[MAX_BTF_ARGS_LEN]; char abuf[MAX_BTF_ARGS_LEN];
char *dbuf = NULL; char *dbuf __free(kfree) = NULL;
bool is_tracepoint = false; bool is_tracepoint = false;
struct module *tp_mod = NULL; struct module *tp_mod __free(module_put) = NULL;
struct tracepoint *tpoint = NULL; struct tracepoint *tpoint = NULL;
struct traceprobe_parse_context ctx = {
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
};
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2) if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2)
return -ECANCELED; return -ECANCELED;
@ -1121,13 +1117,11 @@ static int __trace_fprobe_create(int argc, const char *argv[])
group = TRACEPOINT_EVENT_SYSTEM; group = TRACEPOINT_EVENT_SYSTEM;
} }
trace_probe_log_init("trace_fprobe", argc, argv);
if (argv[0][1] != '\0') { if (argv[0][1] != '\0') {
if (argv[0][1] != ':') { if (argv[0][1] != ':') {
trace_probe_log_set_index(0); trace_probe_log_set_index(0);
trace_probe_log_err(1, BAD_MAXACT); trace_probe_log_err(1, BAD_MAXACT);
goto parse_error; return -EINVAL;
} }
event = &argv[0][2]; event = &argv[0][2];
} }
@ -1137,14 +1131,14 @@ static int __trace_fprobe_create(int argc, const char *argv[])
/* a symbol(or tracepoint) must be specified */ /* a symbol(or tracepoint) must be specified */
ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint); ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint);
if (ret < 0) if (ret < 0)
goto parse_error; return -EINVAL;
trace_probe_log_set_index(0); trace_probe_log_set_index(0);
if (event) { if (event) {
ret = traceprobe_parse_event_name(&event, &group, gbuf, ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]); event - argv[0]);
if (ret) if (ret)
goto parse_error; return -EINVAL;
} }
if (!event) { if (!event) {
@ -1160,49 +1154,44 @@ static int __trace_fprobe_create(int argc, const char *argv[])
} }
if (is_return) if (is_return)
ctx.flags |= TPARG_FL_RETURN; ctx->flags |= TPARG_FL_RETURN;
else else
ctx.flags |= TPARG_FL_FENTRY; ctx->flags |= TPARG_FL_FENTRY;
if (is_tracepoint) { if (is_tracepoint) {
ctx.flags |= TPARG_FL_TPOINT; ctx->flags |= TPARG_FL_TPOINT;
tpoint = find_tracepoint(symbol, &tp_mod); tpoint = find_tracepoint(symbol, &tp_mod);
if (tpoint) { if (tpoint) {
ctx.funcname = kallsyms_lookup( ctx->funcname = kallsyms_lookup(
(unsigned long)tpoint->probestub, (unsigned long)tpoint->probestub,
NULL, NULL, NULL, sbuf); NULL, NULL, NULL, sbuf);
} else if (IS_ENABLED(CONFIG_MODULES)) { } else if (IS_ENABLED(CONFIG_MODULES)) {
/* This *may* be loaded afterwards */ /* This *may* be loaded afterwards */
tpoint = TRACEPOINT_STUB; tpoint = TRACEPOINT_STUB;
ctx.funcname = symbol; ctx->funcname = symbol;
} else { } else {
trace_probe_log_set_index(1); trace_probe_log_set_index(1);
trace_probe_log_err(0, NO_TRACEPOINT); trace_probe_log_err(0, NO_TRACEPOINT);
goto parse_error; return -EINVAL;
} }
} else } else
ctx.funcname = symbol; ctx->funcname = symbol;
argc -= 2; argv += 2; argc -= 2; argv += 2;
new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc, 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)) { if (IS_ERR(new_argv))
ret = PTR_ERR(new_argv); return PTR_ERR(new_argv);
new_argv = NULL;
goto out;
}
if (new_argv) { if (new_argv) {
argc = new_argc; argc = new_argc;
argv = new_argv; argv = new_argv;
} }
if (argc > MAX_TRACE_ARGS) { if (argc > MAX_TRACE_ARGS)
ret = -E2BIG; return -E2BIG;
goto out;
}
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf); ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
if (ret) if (ret)
goto out; return ret;
/* setup a probe */ /* setup a probe */
tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod, tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod,
@ -1211,16 +1200,16 @@ static int __trace_fprobe_create(int argc, const char *argv[])
ret = PTR_ERR(tf); ret = PTR_ERR(tf);
/* This must return -ENOMEM, else there is a bug */ /* This must return -ENOMEM, else there is a bug */
WARN_ON_ONCE(ret != -ENOMEM); WARN_ON_ONCE(ret != -ENOMEM);
goto out; /* We know tf is not allocated */ return ret;
} }
/* parse arguments */ /* parse arguments */
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
trace_probe_log_set_index(i + 2); trace_probe_log_set_index(i + 2);
ctx.offset = 0; ctx->offset = 0;
ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx); ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], ctx);
if (ret) if (ret)
goto error; /* This can be -ENOMEM */ return ret; /* This can be -ENOMEM */
} }
if (is_return && tf->tp.entry_arg) { if (is_return && tf->tp.entry_arg) {
@ -1231,7 +1220,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
ret = traceprobe_set_print_fmt(&tf->tp, ret = traceprobe_set_print_fmt(&tf->tp,
is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL); is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL);
if (ret < 0) if (ret < 0)
goto error; return ret;
ret = register_trace_fprobe(tf); ret = register_trace_fprobe(tf);
if (ret) { if (ret) {
@ -1242,29 +1231,32 @@ static int __trace_fprobe_create(int argc, const char *argv[])
trace_probe_log_err(0, BAD_PROBE_ADDR); trace_probe_log_err(0, BAD_PROBE_ADDR);
else if (ret != -ENOMEM && ret != -EEXIST) else if (ret != -ENOMEM && ret != -EEXIST)
trace_probe_log_err(0, FAIL_REG_PROBE); trace_probe_log_err(0, FAIL_REG_PROBE);
goto error; return -EINVAL;
} }
out: /* 'tf' is successfully registered. To avoid freeing, assign NULL. */
if (tp_mod) tf = NULL;
module_put(tp_mod);
return 0;
}
static int trace_fprobe_create_cb(int argc, const char *argv[])
{
struct traceprobe_parse_context ctx = {
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
};
int ret;
trace_probe_log_init("trace_fprobe", argc, argv);
ret = trace_fprobe_create_internal(argc, argv, &ctx);
traceprobe_finish_parse(&ctx); traceprobe_finish_parse(&ctx);
trace_probe_log_clear(); trace_probe_log_clear();
kfree(new_argv);
kfree(symbol);
kfree(dbuf);
return ret; return ret;
parse_error:
ret = -EINVAL;
error:
free_trace_fprobe(tf);
goto out;
} }
static int trace_fprobe_create(const char *raw_command) static int trace_fprobe_create(const char *raw_command)
{ {
return trace_probe_create(raw_command, __trace_fprobe_create); return trace_probe_create(raw_command, trace_fprobe_create_cb);
} }
static int trace_fprobe_release(struct dyn_event *ev) static int trace_fprobe_release(struct dyn_event *ev)