mirror of https://gitee.com/openkylin/linux.git
perf probe: Release all dynamically allocated parameters
To fix a memory leak, release all dynamically allocated options/parameters in params data structure. This also introduces/exports some init/clear routines. Reported-by: David Ahern <dsahern@gmail.com> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: "David A. Long" <dave.long@linaro.org> Cc: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: yrl.pp-manager.tt@hitachi.com Link: http://lkml.kernel.org/r/20140116093947.24403.80118.stgit@kbuild-fedora.novalocal Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
981d05adf2
commit
e53b00d382
|
@ -59,7 +59,7 @@ static struct {
|
|||
struct perf_probe_event events[MAX_PROBES];
|
||||
struct strlist *dellist;
|
||||
struct line_range line_range;
|
||||
const char *target;
|
||||
char *target;
|
||||
int max_probe_points;
|
||||
struct strfilter *filter;
|
||||
} params;
|
||||
|
@ -98,7 +98,10 @@ static int set_target(const char *ptr)
|
|||
* short module name.
|
||||
*/
|
||||
if (!params.target && ptr && *ptr == '/') {
|
||||
params.target = ptr;
|
||||
params.target = strdup(ptr);
|
||||
if (!params.target)
|
||||
return -ENOMEM;
|
||||
|
||||
found = 1;
|
||||
buf = ptr + (strlen(ptr) - 3);
|
||||
|
||||
|
@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv)
|
|||
char *buf;
|
||||
|
||||
found_target = set_target(argv[0]);
|
||||
if (found_target < 0)
|
||||
return found_target;
|
||||
|
||||
if (found_target && argc == 1)
|
||||
return 0;
|
||||
|
||||
|
@ -217,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused,
|
|||
|
||||
params.show_lines = true;
|
||||
ret = parse_line_range_desc(str, ¶ms.line_range);
|
||||
INIT_LIST_HEAD(¶ms.line_range.line_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -263,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
static void init_params(void)
|
||||
{
|
||||
line_range__init(¶ms.line_range);
|
||||
}
|
||||
|
||||
static void cleanup_params(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < params.nevents; i++)
|
||||
clear_perf_probe_event(params.events + i);
|
||||
if (params.dellist)
|
||||
strlist__delete(params.dellist);
|
||||
line_range__clear(¶ms.line_range);
|
||||
free(params.target);
|
||||
if (params.filter)
|
||||
strfilter__delete(params.filter);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
}
|
||||
|
||||
static int
|
||||
__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
{
|
||||
const char * const probe_usage[] = {
|
||||
"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
|
||||
|
@ -417,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
ret = show_available_funcs(params.target, params.filter,
|
||||
params.uprobes);
|
||||
strfilter__delete(params.filter);
|
||||
params.filter = NULL;
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show functions."
|
||||
" (%d)\n", ret);
|
||||
|
@ -456,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
params.filter,
|
||||
params.show_ext_vars);
|
||||
strfilter__delete(params.filter);
|
||||
params.filter = NULL;
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show vars. (%d)\n", ret);
|
||||
return ret;
|
||||
|
@ -464,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
|
||||
if (params.dellist) {
|
||||
ret = del_perf_probe_events(params.dellist);
|
||||
strlist__delete(params.dellist);
|
||||
if (ret < 0) {
|
||||
pr_err(" Error: Failed to delete events. (%d)\n", ret);
|
||||
return ret;
|
||||
|
@ -483,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_probe(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int ret;
|
||||
|
||||
init_params();
|
||||
ret = __cmd_probe(argc, argv, prefix);
|
||||
cleanup_params();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -794,6 +794,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
|
|||
}
|
||||
#endif
|
||||
|
||||
void line_range__clear(struct line_range *lr)
|
||||
{
|
||||
struct line_node *ln;
|
||||
|
||||
free(lr->function);
|
||||
free(lr->file);
|
||||
free(lr->path);
|
||||
free(lr->comp_dir);
|
||||
while (!list_empty(&lr->line_list)) {
|
||||
ln = list_first_entry(&lr->line_list, struct line_node, list);
|
||||
list_del(&ln->list);
|
||||
free(ln);
|
||||
}
|
||||
memset(lr, 0, sizeof(*lr));
|
||||
}
|
||||
|
||||
void line_range__init(struct line_range *lr)
|
||||
{
|
||||
memset(lr, 0, sizeof(*lr));
|
||||
INIT_LIST_HEAD(&lr->line_list);
|
||||
}
|
||||
|
||||
static int parse_line_num(char **ptr, int *val, const char *what)
|
||||
{
|
||||
const char *start = *ptr;
|
||||
|
|
|
@ -120,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev);
|
|||
/* Command string to line-range */
|
||||
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
|
||||
|
||||
/* Release line range members */
|
||||
extern void line_range__clear(struct line_range *lr);
|
||||
|
||||
/* Initialize line range */
|
||||
extern void line_range__init(struct line_range *lr);
|
||||
|
||||
/* Internal use: Return kernel/module path */
|
||||
extern const char *kernel_get_module_path(const char *module);
|
||||
|
||||
|
|
Loading…
Reference in New Issue