Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932292AbbGPRXs (ORCPT ); Thu, 16 Jul 2015 13:23:48 -0400 Received: from mga14.intel.com ([192.55.52.115]:54496 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932247AbbGPRXo (ORCPT ); Thu, 16 Jul 2015 13:23:44 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,488,1432623600"; d="scan'208";a="525475316" From: Tom Zanussi To: rostedt@goodmis.org Cc: daniel.wagner@bmw-carit.de, masami.hiramatsu.pt@hitachi.com, namhyung@kernel.org, josh@joshtriplett.org, andi@firstfloor.org, linux-kernel@vger.kernel.org, Tom Zanussi Subject: [PATCH v9 10/22] tracing: Add hist trigger support for compound keys Date: Thu, 16 Jul 2015 12:22:43 -0500 Message-Id: <119af14e85f75fe807b49631f89c4ca45d6441bb.1437066836.git.tom.zanussi@linux.intel.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6490 Lines: 174 Allow users to specify multiple trace event fields to use in keys by allowing multiple fields in the 'keys=' keyword. With this addition, any unique combination of any of the fields named in the 'keys' keyword will result in a new entry being added to the hash table. Signed-off-by: Tom Zanussi --- kernel/trace/trace.c | 8 +++++--- kernel/trace/trace_events_hist.c | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8109b89..1e4801e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3787,19 +3787,21 @@ static const char readme_msg[] = "\t Filters can be ignored when removing a trigger.\n" #ifdef CONFIG_HIST_TRIGGERS " hist trigger\t- If set, event hits are aggregated into a hash table\n" - "\t Format: hist:keys=\n" + "\t Format: hist:keys=[,field2,...]\n" "\t [:values=]\n\n" "\t When a matching event is hit, an entry is added to a hash\n" - "\t table using the key and value(s) named. Keys and values\n" + "\t table using the key(s) and value(s) named. Keys and values\n" "\t correspond to fields in the event's format description.\n" "\t Values must correspond to numeric fields - on an event hit,\n" "\t the value(s) will be added to a sum kept for that field.\n" "\t The special string 'hitcount' can be used in place of an\n" "\t explicit value field - this is simply a count of event hits.\n" "\t If 'values' is not specified, 'hitcount' will be assumed.\n" - "\t of event hits. Keys can be any field.\n\n" + "\t of event hits. Keys can be any field. Compound keys\n" + "\t consisting of up to two fields can be specified by the 'keys'\n" + "\t keyword.\n\n" "\t Reading the 'hist' file for the event will dump the hash\n" "\t table in its entirety to stdout. Each printed hash table\n" "\t entry is a simple list of the keys and values comprising the\n" diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 503df07..3d5433a 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -32,6 +32,7 @@ struct hist_field { unsigned long flags; hist_field_fn_t fn; unsigned int size; + unsigned int offset; }; static u64 hist_field_counter(struct hist_field *field, void *event) @@ -64,8 +65,8 @@ DEFINE_HIST_FIELD_FN(s8); DEFINE_HIST_FIELD_FN(u8); #define HITCOUNT_IDX 0 -#define HIST_KEY_MAX 1 -#define HIST_KEY_SIZE_MAX MAX_FILTER_STR_VAL +#define HIST_KEY_MAX 2 +#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + sizeof(u64)) enum hist_field_flags { HIST_FIELD_HITCOUNT = 1, @@ -327,6 +328,7 @@ static int create_val_fields(struct hist_trigger_data *hist_data, static int create_key_field(struct hist_trigger_data *hist_data, unsigned int key_idx, + unsigned int key_offset, struct trace_event_file *file, char *field_str) { @@ -353,7 +355,8 @@ static int create_key_field(struct hist_trigger_data *hist_data, key_size = ALIGN(key_size, sizeof(u64)); hist_data->fields[key_idx]->size = key_size; - hist_data->key_size = key_size; + hist_data->fields[key_idx]->offset = key_offset; + hist_data->key_size += key_size; if (hist_data->key_size > HIST_KEY_SIZE_MAX) { ret = -EINVAL; goto out; @@ -368,7 +371,7 @@ static int create_key_field(struct hist_trigger_data *hist_data, static int create_key_fields(struct hist_trigger_data *hist_data, struct trace_event_file *file) { - unsigned int i, n_vals = hist_data->n_vals; + unsigned int i, key_offset = 0, n_vals = hist_data->n_vals; char *fields_str, *field_str; int ret = -EINVAL; @@ -384,9 +387,11 @@ static int create_key_fields(struct hist_trigger_data *hist_data, field_str = strsep(&fields_str, ","); if (!field_str) break; - ret = create_key_field(hist_data, i, file, field_str); + ret = create_key_field(hist_data, i, key_offset, + file, field_str); if (ret < 0) goto out; + key_offset += ret; } if (fields_str) { ret = -EINVAL; @@ -451,7 +456,10 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) else cmp_fn = tracing_map_cmp_num(field->size, field->is_signed); - idx = tracing_map_add_key_field(map, 0, cmp_fn); + idx = tracing_map_add_key_field(map, + hist_field->offset, + cmp_fn); + } else idx = tracing_map_add_sum_field(map); @@ -531,6 +539,7 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, static void event_hist_trigger(struct event_trigger_data *data, void *rec) { struct hist_trigger_data *hist_data = data->private_data; + char compound_key[HIST_KEY_SIZE_MAX]; struct hist_field *key_field; struct tracing_map_elt *elt; u64 field_contents; @@ -542,6 +551,9 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) return; } + if (hist_data->n_keys > 1) + memset(compound_key, 0, hist_data->key_size); + for (i = hist_data->n_vals; i < hist_data->n_fields; i++) { key_field = hist_data->fields[i]; @@ -550,8 +562,16 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec) key = (void *)field_contents; else key = (void *)&field_contents; + + if (hist_data->n_keys > 1) { + memcpy(compound_key + key_field->offset, key, + key_field->size); + } } + if (hist_data->n_keys > 1) + key = compound_key; + elt = tracing_map_insert(hist_data->map, key); if (elt) hist_trigger_elt_update(hist_data, elt, rec); @@ -580,11 +600,11 @@ hist_trigger_entry_print(struct seq_file *m, if (key_field->flags & HIST_FIELD_STRING) { seq_printf(m, "%s: %-35s", key_field->field->name, - (char *)key); + (char *)(key + key_field->offset)); } else { - uval = *(u64 *)key; - seq_printf(m, "%s: %10llu", - key_field->field->name, uval); + uval = *(u64 *)(key + key_field->offset); + seq_printf(m, "%s: %10llu", key_field->field->name, + uval); } } -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/