| From 4d5065bbd407b1f48ed2f655ef708671a725bba0 Mon Sep 17 00:00:00 2001 |
| From: Tom Zanussi <tom.zanussi@linux.intel.com> |
| Date: Mon, 15 Jan 2018 20:51:53 -0600 |
| Subject: [PATCH 1765/1795] tracing: Generalize per-element hist trigger data |
| |
| Up until now, hist triggers only needed per-element support for saving |
| 'comm' data, which was saved directly as a private data pointer. |
| |
| In anticipation of the need to save other data besides 'comm', add a |
| new hist_elt_data struct for the purpose, and switch the current |
| 'comm'-related code over to that. |
| |
| Link: http://lkml.kernel.org/r/4502c338c965ddf5fc19fb1ec4764391e001ed4b.1516069914.git.tom.zanussi@linux.intel.com |
| |
| Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| (cherry picked from commit af6a29bcaf8ff260222a953536c13c167d5c4649) |
| Signed-off-by: Hirotaka MOTAI <Motai.Hirotaka@aj.MitsubishiElectric.co.jp> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| kernel/trace/trace_events_hist.c | 76 ++++++++++++++++++-------------- |
| 1 file changed, 43 insertions(+), 33 deletions(-) |
| |
| diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c |
| index 4c3c7d784bfd..f072ed3122c8 100644 |
| --- a/kernel/trace/trace_events_hist.c |
| +++ b/kernel/trace/trace_events_hist.c |
| @@ -289,6 +289,10 @@ static struct hist_field *find_var(struct hist_trigger_data *hist_data, |
| return NULL; |
| } |
| |
| +struct hist_elt_data { |
| + char *comm; |
| +}; |
| + |
| static const char *hist_field_name(struct hist_field *field, |
| unsigned int level) |
| { |
| @@ -503,45 +507,61 @@ static inline void save_comm(char *comm, struct task_struct *task) |
| memcpy(comm, task->comm, TASK_COMM_LEN); |
| } |
| |
| -static void hist_trigger_elt_comm_free(struct tracing_map_elt *elt) |
| +static void hist_elt_data_free(struct hist_elt_data *elt_data) |
| +{ |
| + kfree(elt_data->comm); |
| + kfree(elt_data); |
| +} |
| + |
| +static void hist_trigger_elt_data_free(struct tracing_map_elt *elt) |
| { |
| - kfree((char *)elt->private_data); |
| + struct hist_elt_data *elt_data = elt->private_data; |
| + |
| + hist_elt_data_free(elt_data); |
| } |
| |
| -static int hist_trigger_elt_comm_alloc(struct tracing_map_elt *elt) |
| +static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt) |
| { |
| struct hist_trigger_data *hist_data = elt->map->private_data; |
| + unsigned int size = TASK_COMM_LEN; |
| + struct hist_elt_data *elt_data; |
| struct hist_field *key_field; |
| unsigned int i; |
| |
| + elt_data = kzalloc(sizeof(*elt_data), GFP_KERNEL); |
| + if (!elt_data) |
| + return -ENOMEM; |
| + |
| for_each_hist_key_field(i, hist_data) { |
| key_field = hist_data->fields[i]; |
| |
| if (key_field->flags & HIST_FIELD_FL_EXECNAME) { |
| - unsigned int size = TASK_COMM_LEN + 1; |
| - |
| - elt->private_data = kzalloc(size, GFP_KERNEL); |
| - if (!elt->private_data) |
| + elt_data->comm = kzalloc(size, GFP_KERNEL); |
| + if (!elt_data->comm) { |
| + kfree(elt_data); |
| return -ENOMEM; |
| + } |
| break; |
| } |
| } |
| |
| + elt->private_data = elt_data; |
| + |
| return 0; |
| } |
| |
| -static void hist_trigger_elt_comm_init(struct tracing_map_elt *elt) |
| +static void hist_trigger_elt_data_init(struct tracing_map_elt *elt) |
| { |
| - char *comm = elt->private_data; |
| + struct hist_elt_data *elt_data = elt->private_data; |
| |
| - if (comm) |
| - save_comm(comm, current); |
| + if (elt_data->comm) |
| + save_comm(elt_data->comm, current); |
| } |
| |
| -static const struct tracing_map_ops hist_trigger_elt_comm_ops = { |
| - .elt_alloc = hist_trigger_elt_comm_alloc, |
| - .elt_free = hist_trigger_elt_comm_free, |
| - .elt_init = hist_trigger_elt_comm_init, |
| +static const struct tracing_map_ops hist_trigger_elt_data_ops = { |
| + .elt_alloc = hist_trigger_elt_data_alloc, |
| + .elt_free = hist_trigger_elt_data_free, |
| + .elt_init = hist_trigger_elt_data_init, |
| }; |
| |
| static const char *get_hist_field_flags(struct hist_field *hist_field) |
| @@ -1484,21 +1504,6 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) |
| return 0; |
| } |
| |
| -static bool need_tracing_map_ops(struct hist_trigger_data *hist_data) |
| -{ |
| - struct hist_field *key_field; |
| - unsigned int i; |
| - |
| - for_each_hist_key_field(i, hist_data) { |
| - key_field = hist_data->fields[i]; |
| - |
| - if (key_field->flags & HIST_FIELD_FL_EXECNAME) |
| - return true; |
| - } |
| - |
| - return false; |
| -} |
| - |
| static struct hist_trigger_data * |
| create_hist_data(unsigned int map_bits, |
| struct hist_trigger_attrs *attrs, |
| @@ -1524,8 +1529,7 @@ create_hist_data(unsigned int map_bits, |
| if (ret) |
| goto free; |
| |
| - if (need_tracing_map_ops(hist_data)) |
| - map_ops = &hist_trigger_elt_comm_ops; |
| + map_ops = &hist_trigger_elt_data_ops; |
| |
| hist_data->map = tracing_map_create(map_bits, hist_data->key_size, |
| map_ops, hist_data); |
| @@ -1713,7 +1717,13 @@ hist_trigger_entry_print(struct seq_file *m, |
| seq_printf(m, "%s: [%llx] %-55s", field_name, |
| uval, str); |
| } else if (key_field->flags & HIST_FIELD_FL_EXECNAME) { |
| - char *comm = elt->private_data; |
| + struct hist_elt_data *elt_data = elt->private_data; |
| + char *comm; |
| + |
| + if (WARN_ON_ONCE(!elt_data)) |
| + return; |
| + |
| + comm = elt_data->comm; |
| |
| uval = *(u64 *)(key + key_field->offset); |
| seq_printf(m, "%s: %-16s[%10llu]", field_name, |
| -- |
| 2.19.0 |
| |