Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-10 Thread Tom Zanussi
Hi Namhyung,

On Fri, 2017-11-10 at 16:28 +0900, Namhyung Kim wrote:
> Hi Tom,
> 
> On Thu, Nov 09, 2017 at 02:33:46PM -0600, Tom Zanussi wrote:
> > Add support for saving the value of a current event's event field by
> > assigning it to a variable that can be read by a subsequent event.
> > 
> > The basic syntax for saving a variable is to simply prefix a unique
> > variable name not corresponding to any keyword along with an '=' sign
> > to any event field.
> > 
> > Both keys and values can be saved and retrieved in this way:
> > 
> > # echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
> > # echo 'hist:timer_pid=common_pid:key=$timer_pid ...'
> > 
> > If a variable isn't a key variable or prefixed with 'vals=', the
> > associated event field will be saved in a variable but won't be summed
> > as a value:
> > 
> > # echo 'hist:keys=next_pid:ts1=$common_timestamp:...
> > 
> > Multiple variables can be assigned at the same time:
> > 
> > # echo 
> > 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 ...
> > 
> > Multiple (or single) variables can also be assigned at the same time
> > using separate assignments:
> > 
> > # echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 
> > ...
> > 
> > Variables set as above can be used by being referenced from another
> > event, as described in a subsequent patch.
> > 
> > Signed-off-by: Tom Zanussi 
> > Signed-off-by: Baohong Liu 
> > ---
> 
> [SNIP]
> > +static int parse_var_defs(struct hist_trigger_data *hist_data)
> > +{
> > +   char *s, *str, *var_name, *field_str;
> > +   unsigned int i, j, n_vars = 0;
> > +   int ret = 0;
> > +
> > +   for (i = 0; i < hist_data->attrs->n_assignments; i++) {
> > +   str = hist_data->attrs->assignment_str[i];
> > +   for (j = 0; j < TRACING_MAP_VARS_MAX; j++) {
> > +   field_str = strsep(, ",");
> > +   if (!field_str)
> > +   break;
> > +
> > +   var_name = strsep(_str, "=");
> > +   if (!var_name || !field_str) {
> > +   ret = -EINVAL;
> > +   goto free;
> > +   }
> > +
> > +   s = kstrdup(var_name, GFP_KERNEL);
> > +   if (!s) {
> > +   ret = -ENOMEM;
> > +   goto free;
> > +   }
> > +   hist_data->attrs->var_defs.name[n_vars] = s;
> > +
> > +   s = kstrdup(field_str, GFP_KERNEL);
> > +   if (!s) {
> > +   kfree(hist_data->attrs->var_defs.name[n_vars]);
> > +   ret = -ENOMEM;
> > +   goto free;
> > +   }
> > +   hist_data->attrs->var_defs.expr[n_vars++] = s;
> > +
> > +   hist_data->attrs->var_defs.n_vars = n_vars;
> > +
> > +   if (n_vars == TRACING_MAP_VARS_MAX)
> > +   goto free;
> 
> This will silently discard all variables.  Why not returning an error?
> Also I think it should be moved to the beginning of this block..
> 

Yes, thanks for pointing this out.

This should fix it, will merge into the appropriate patches in the next
version...

Tom


From: Tom Zanussi 
Date: Fri, 10 Nov 2017 09:01:21 -0600
Subject: [PATCH] tracing: Fix parse_var_defs max case

Fix the VARS_MAX case and add an error condition for it.

Merge into variable support and 'last err' patches.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_hist.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 4d1b636..1ea9304 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -4050,6 +4050,12 @@ static int parse_var_defs(struct hist_trigger_data 
*hist_data)
goto free;
}
 
+   if (n_vars == TRACING_MAP_VARS_MAX) {
+   hist_err("Too many variables defined: ", 
var_name);
+   ret = -EINVAL;
+   goto free;
+   }
+
s = kstrdup(var_name, GFP_KERNEL);
if (!s) {
ret = -ENOMEM;
@@ -4066,9 +4072,6 @@ static int parse_var_defs(struct hist_trigger_data 
*hist_data)
hist_data->attrs->var_defs.expr[n_vars++] = s;
 
hist_data->attrs->var_defs.n_vars = n_vars;
-
-   if (n_vars == TRACING_MAP_VARS_MAX)
-   goto free;
}
}
 
-- 
2.7.4





Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-10 Thread Tom Zanussi
Hi Namhyung,

On Fri, 2017-11-10 at 16:28 +0900, Namhyung Kim wrote:
> Hi Tom,
> 
> On Thu, Nov 09, 2017 at 02:33:46PM -0600, Tom Zanussi wrote:
> > Add support for saving the value of a current event's event field by
> > assigning it to a variable that can be read by a subsequent event.
> > 
> > The basic syntax for saving a variable is to simply prefix a unique
> > variable name not corresponding to any keyword along with an '=' sign
> > to any event field.
> > 
> > Both keys and values can be saved and retrieved in this way:
> > 
> > # echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
> > # echo 'hist:timer_pid=common_pid:key=$timer_pid ...'
> > 
> > If a variable isn't a key variable or prefixed with 'vals=', the
> > associated event field will be saved in a variable but won't be summed
> > as a value:
> > 
> > # echo 'hist:keys=next_pid:ts1=$common_timestamp:...
> > 
> > Multiple variables can be assigned at the same time:
> > 
> > # echo 
> > 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 ...
> > 
> > Multiple (or single) variables can also be assigned at the same time
> > using separate assignments:
> > 
> > # echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 
> > ...
> > 
> > Variables set as above can be used by being referenced from another
> > event, as described in a subsequent patch.
> > 
> > Signed-off-by: Tom Zanussi 
> > Signed-off-by: Baohong Liu 
> > ---
> 
> [SNIP]
> > +static int parse_var_defs(struct hist_trigger_data *hist_data)
> > +{
> > +   char *s, *str, *var_name, *field_str;
> > +   unsigned int i, j, n_vars = 0;
> > +   int ret = 0;
> > +
> > +   for (i = 0; i < hist_data->attrs->n_assignments; i++) {
> > +   str = hist_data->attrs->assignment_str[i];
> > +   for (j = 0; j < TRACING_MAP_VARS_MAX; j++) {
> > +   field_str = strsep(, ",");
> > +   if (!field_str)
> > +   break;
> > +
> > +   var_name = strsep(_str, "=");
> > +   if (!var_name || !field_str) {
> > +   ret = -EINVAL;
> > +   goto free;
> > +   }
> > +
> > +   s = kstrdup(var_name, GFP_KERNEL);
> > +   if (!s) {
> > +   ret = -ENOMEM;
> > +   goto free;
> > +   }
> > +   hist_data->attrs->var_defs.name[n_vars] = s;
> > +
> > +   s = kstrdup(field_str, GFP_KERNEL);
> > +   if (!s) {
> > +   kfree(hist_data->attrs->var_defs.name[n_vars]);
> > +   ret = -ENOMEM;
> > +   goto free;
> > +   }
> > +   hist_data->attrs->var_defs.expr[n_vars++] = s;
> > +
> > +   hist_data->attrs->var_defs.n_vars = n_vars;
> > +
> > +   if (n_vars == TRACING_MAP_VARS_MAX)
> > +   goto free;
> 
> This will silently discard all variables.  Why not returning an error?
> Also I think it should be moved to the beginning of this block..
> 

Yes, thanks for pointing this out.

This should fix it, will merge into the appropriate patches in the next
version...

Tom


From: Tom Zanussi 
Date: Fri, 10 Nov 2017 09:01:21 -0600
Subject: [PATCH] tracing: Fix parse_var_defs max case

Fix the VARS_MAX case and add an error condition for it.

Merge into variable support and 'last err' patches.

Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_hist.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 4d1b636..1ea9304 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -4050,6 +4050,12 @@ static int parse_var_defs(struct hist_trigger_data 
*hist_data)
goto free;
}
 
+   if (n_vars == TRACING_MAP_VARS_MAX) {
+   hist_err("Too many variables defined: ", 
var_name);
+   ret = -EINVAL;
+   goto free;
+   }
+
s = kstrdup(var_name, GFP_KERNEL);
if (!s) {
ret = -ENOMEM;
@@ -4066,9 +4072,6 @@ static int parse_var_defs(struct hist_trigger_data 
*hist_data)
hist_data->attrs->var_defs.expr[n_vars++] = s;
 
hist_data->attrs->var_defs.n_vars = n_vars;
-
-   if (n_vars == TRACING_MAP_VARS_MAX)
-   goto free;
}
}
 
-- 
2.7.4





Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-10 Thread Steven Rostedt
On Fri, 10 Nov 2017 16:28:41 +0900
Namhyung Kim  wrote:

> > +   hist_data->attrs->var_defs.expr[n_vars++] = s;
> > +
> > +   hist_data->attrs->var_defs.n_vars = n_vars;
> > +
> > +   if (n_vars == TRACING_MAP_VARS_MAX)
> > +   goto free;  
> 
> This will silently discard all variables.  Why not returning an error?
> Also I think it should be moved to the beginning of this block..

Right, because the check here is already too late. Usually you check
the count before doing the assignment.


if (n_vars == TRACING_MAP_VARS_MAX)
goto free;

hist_data->attrs->var_defs.expr[n_vars++] = s;

Because it is OK for n_vars to equal TRACING_MAP_VARS_MAX, but not OK
to be more.

-- Steve


Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-10 Thread Steven Rostedt
On Fri, 10 Nov 2017 16:28:41 +0900
Namhyung Kim  wrote:

> > +   hist_data->attrs->var_defs.expr[n_vars++] = s;
> > +
> > +   hist_data->attrs->var_defs.n_vars = n_vars;
> > +
> > +   if (n_vars == TRACING_MAP_VARS_MAX)
> > +   goto free;  
> 
> This will silently discard all variables.  Why not returning an error?
> Also I think it should be moved to the beginning of this block..

Right, because the check here is already too late. Usually you check
the count before doing the assignment.


if (n_vars == TRACING_MAP_VARS_MAX)
goto free;

hist_data->attrs->var_defs.expr[n_vars++] = s;

Because it is OK for n_vars to equal TRACING_MAP_VARS_MAX, but not OK
to be more.

-- Steve


Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-09 Thread Namhyung Kim
Hi Tom,

On Thu, Nov 09, 2017 at 02:33:46PM -0600, Tom Zanussi wrote:
> Add support for saving the value of a current event's event field by
> assigning it to a variable that can be read by a subsequent event.
> 
> The basic syntax for saving a variable is to simply prefix a unique
> variable name not corresponding to any keyword along with an '=' sign
> to any event field.
> 
> Both keys and values can be saved and retrieved in this way:
> 
> # echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
> # echo 'hist:timer_pid=common_pid:key=$timer_pid ...'
> 
> If a variable isn't a key variable or prefixed with 'vals=', the
> associated event field will be saved in a variable but won't be summed
> as a value:
> 
> # echo 'hist:keys=next_pid:ts1=$common_timestamp:...
> 
> Multiple variables can be assigned at the same time:
> 
> # echo 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 
> ...
> 
> Multiple (or single) variables can also be assigned at the same time
> using separate assignments:
> 
> # echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 
> ...
> 
> Variables set as above can be used by being referenced from another
> event, as described in a subsequent patch.
> 
> Signed-off-by: Tom Zanussi 
> Signed-off-by: Baohong Liu 
> ---

[SNIP]
> +static int parse_var_defs(struct hist_trigger_data *hist_data)
> +{
> + char *s, *str, *var_name, *field_str;
> + unsigned int i, j, n_vars = 0;
> + int ret = 0;
> +
> + for (i = 0; i < hist_data->attrs->n_assignments; i++) {
> + str = hist_data->attrs->assignment_str[i];
> + for (j = 0; j < TRACING_MAP_VARS_MAX; j++) {
> + field_str = strsep(, ",");
> + if (!field_str)
> + break;
> +
> + var_name = strsep(_str, "=");
> + if (!var_name || !field_str) {
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + s = kstrdup(var_name, GFP_KERNEL);
> + if (!s) {
> + ret = -ENOMEM;
> + goto free;
> + }
> + hist_data->attrs->var_defs.name[n_vars] = s;
> +
> + s = kstrdup(field_str, GFP_KERNEL);
> + if (!s) {
> + kfree(hist_data->attrs->var_defs.name[n_vars]);
> + ret = -ENOMEM;
> + goto free;
> + }
> + hist_data->attrs->var_defs.expr[n_vars++] = s;
> +
> + hist_data->attrs->var_defs.n_vars = n_vars;
> +
> + if (n_vars == TRACING_MAP_VARS_MAX)
> + goto free;

This will silently discard all variables.  Why not returning an error?
Also I think it should be moved to the beginning of this block..

Thanks,
Namhyung


> + }
> + }
> +
> + return ret;
> + free:
> + free_var_defs(hist_data);
> +
> + return ret;
> +}


Re: [PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-09 Thread Namhyung Kim
Hi Tom,

On Thu, Nov 09, 2017 at 02:33:46PM -0600, Tom Zanussi wrote:
> Add support for saving the value of a current event's event field by
> assigning it to a variable that can be read by a subsequent event.
> 
> The basic syntax for saving a variable is to simply prefix a unique
> variable name not corresponding to any keyword along with an '=' sign
> to any event field.
> 
> Both keys and values can be saved and retrieved in this way:
> 
> # echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
> # echo 'hist:timer_pid=common_pid:key=$timer_pid ...'
> 
> If a variable isn't a key variable or prefixed with 'vals=', the
> associated event field will be saved in a variable but won't be summed
> as a value:
> 
> # echo 'hist:keys=next_pid:ts1=$common_timestamp:...
> 
> Multiple variables can be assigned at the same time:
> 
> # echo 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 
> ...
> 
> Multiple (or single) variables can also be assigned at the same time
> using separate assignments:
> 
> # echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 
> ...
> 
> Variables set as above can be used by being referenced from another
> event, as described in a subsequent patch.
> 
> Signed-off-by: Tom Zanussi 
> Signed-off-by: Baohong Liu 
> ---

[SNIP]
> +static int parse_var_defs(struct hist_trigger_data *hist_data)
> +{
> + char *s, *str, *var_name, *field_str;
> + unsigned int i, j, n_vars = 0;
> + int ret = 0;
> +
> + for (i = 0; i < hist_data->attrs->n_assignments; i++) {
> + str = hist_data->attrs->assignment_str[i];
> + for (j = 0; j < TRACING_MAP_VARS_MAX; j++) {
> + field_str = strsep(, ",");
> + if (!field_str)
> + break;
> +
> + var_name = strsep(_str, "=");
> + if (!var_name || !field_str) {
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + s = kstrdup(var_name, GFP_KERNEL);
> + if (!s) {
> + ret = -ENOMEM;
> + goto free;
> + }
> + hist_data->attrs->var_defs.name[n_vars] = s;
> +
> + s = kstrdup(field_str, GFP_KERNEL);
> + if (!s) {
> + kfree(hist_data->attrs->var_defs.name[n_vars]);
> + ret = -ENOMEM;
> + goto free;
> + }
> + hist_data->attrs->var_defs.expr[n_vars++] = s;
> +
> + hist_data->attrs->var_defs.n_vars = n_vars;
> +
> + if (n_vars == TRACING_MAP_VARS_MAX)
> + goto free;

This will silently discard all variables.  Why not returning an error?
Also I think it should be moved to the beginning of this block..

Thanks,
Namhyung


> + }
> + }
> +
> + return ret;
> + free:
> + free_var_defs(hist_data);
> +
> + return ret;
> +}


[PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-09 Thread Tom Zanussi
Add support for saving the value of a current event's event field by
assigning it to a variable that can be read by a subsequent event.

The basic syntax for saving a variable is to simply prefix a unique
variable name not corresponding to any keyword along with an '=' sign
to any event field.

Both keys and values can be saved and retrieved in this way:

# echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
# echo 'hist:timer_pid=common_pid:key=$timer_pid ...'

If a variable isn't a key variable or prefixed with 'vals=', the
associated event field will be saved in a variable but won't be summed
as a value:

# echo 'hist:keys=next_pid:ts1=$common_timestamp:...

Multiple variables can be assigned at the same time:

# echo 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 ...

Multiple (or single) variables can also be assigned at the same time
using separate assignments:

# echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 ...

Variables set as above can be used by being referenced from another
event, as described in a subsequent patch.

Signed-off-by: Tom Zanussi 
Signed-off-by: Baohong Liu 
---
 kernel/trace/trace_events_hist.c | 367 ++-
 1 file changed, 327 insertions(+), 40 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index ec2df88..a7eb162 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -30,6 +30,13 @@ typedef u64 (*hist_field_fn_t) (struct hist_field *field, 
void *event,
struct ring_buffer_event *rbe);
 
 #define HIST_FIELD_OPERANDS_MAX2
+#define HIST_FIELDS_MAX(TRACING_MAP_FIELDS_MAX + 
TRACING_MAP_VARS_MAX)
+
+struct hist_var {
+   char*name;
+   struct hist_trigger_data*hist_data;
+   unsigned intidx;
+};
 
 struct hist_field {
struct ftrace_event_field   *field;
@@ -40,6 +47,7 @@ struct hist_field {
unsigned intis_signed;
struct hist_field   *operands[HIST_FIELD_OPERANDS_MAX];
struct hist_trigger_data*hist_data;
+   struct hist_var var;
 };
 
 static u64 hist_field_none(struct hist_field *field, void *event,
@@ -138,6 +146,13 @@ enum hist_field_flags {
HIST_FIELD_FL_LOG2  = 1 << 9,
HIST_FIELD_FL_TIMESTAMP = 1 << 10,
HIST_FIELD_FL_TIMESTAMP_USECS   = 1 << 11,
+   HIST_FIELD_FL_VAR   = 1 << 12,
+};
+
+struct var_defs {
+   unsigned intn_vars;
+   char*name[TRACING_MAP_VARS_MAX];
+   char*expr[TRACING_MAP_VARS_MAX];
 };
 
 struct hist_trigger_attrs {
@@ -150,13 +165,19 @@ struct hist_trigger_attrs {
boolclear;
boolts_in_usecs;
unsigned intmap_bits;
+
+   char*assignment_str[TRACING_MAP_VARS_MAX];
+   unsigned intn_assignments;
+
+   struct var_defs var_defs;
 };
 
 struct hist_trigger_data {
-   struct hist_field   *fields[TRACING_MAP_FIELDS_MAX];
+   struct hist_field   *fields[HIST_FIELDS_MAX];
unsigned intn_vals;
unsigned intn_keys;
unsigned intn_fields;
+   unsigned intn_vars;
unsigned intkey_size;
struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
unsigned intn_sort_keys;
@@ -164,6 +185,7 @@ struct hist_trigger_data {
struct hist_trigger_attrs   *attrs;
struct tracing_map  *map;
boolenable_timestamps;
+   boolremove;
 };
 
 static u64 hist_field_timestamp(struct hist_field *hist_field, void *event,
@@ -262,9 +284,14 @@ static int parse_map_size(char *str)
 
 static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs)
 {
+   unsigned int i;
+
if (!attrs)
return;
 
+   for (i = 0; i < attrs->n_assignments; i++)
+   kfree(attrs->assignment_str[i]);
+
kfree(attrs->name);
kfree(attrs->sort_key_str);
kfree(attrs->keys_str);
@@ -311,8 +338,22 @@ static int parse_assignment(char *str, struct 
hist_trigger_attrs *attrs)
goto out;
}
attrs->map_bits = map_bits;
-   } else
-   ret = -EINVAL;
+   } else {
+   char *assignment;
+
+   if (attrs->n_assignments == TRACING_MAP_VARS_MAX) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   assignment = kstrdup(str, GFP_KERNEL);
+   if (!assignment) {
+  

[PATCH v5 15/37] tracing: Add variable support to hist triggers

2017-11-09 Thread Tom Zanussi
Add support for saving the value of a current event's event field by
assigning it to a variable that can be read by a subsequent event.

The basic syntax for saving a variable is to simply prefix a unique
variable name not corresponding to any keyword along with an '=' sign
to any event field.

Both keys and values can be saved and retrieved in this way:

# echo 'hist:keys=next_pid:vals=$ts0:ts0=$common_timestamp ...
# echo 'hist:timer_pid=common_pid:key=$timer_pid ...'

If a variable isn't a key variable or prefixed with 'vals=', the
associated event field will be saved in a variable but won't be summed
as a value:

# echo 'hist:keys=next_pid:ts1=$common_timestamp:...

Multiple variables can be assigned at the same time:

# echo 'hist:keys=pid:vals=$ts0,$b,field2:ts0=$common_timestamp,b=field1 ...

Multiple (or single) variables can also be assigned at the same time
using separate assignments:

# echo 'hist:keys=pid:vals=$ts0:ts0=$common_timestamp:b=field1:c=field2 ...

Variables set as above can be used by being referenced from another
event, as described in a subsequent patch.

Signed-off-by: Tom Zanussi 
Signed-off-by: Baohong Liu 
---
 kernel/trace/trace_events_hist.c | 367 ++-
 1 file changed, 327 insertions(+), 40 deletions(-)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index ec2df88..a7eb162 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -30,6 +30,13 @@ typedef u64 (*hist_field_fn_t) (struct hist_field *field, 
void *event,
struct ring_buffer_event *rbe);
 
 #define HIST_FIELD_OPERANDS_MAX2
+#define HIST_FIELDS_MAX(TRACING_MAP_FIELDS_MAX + 
TRACING_MAP_VARS_MAX)
+
+struct hist_var {
+   char*name;
+   struct hist_trigger_data*hist_data;
+   unsigned intidx;
+};
 
 struct hist_field {
struct ftrace_event_field   *field;
@@ -40,6 +47,7 @@ struct hist_field {
unsigned intis_signed;
struct hist_field   *operands[HIST_FIELD_OPERANDS_MAX];
struct hist_trigger_data*hist_data;
+   struct hist_var var;
 };
 
 static u64 hist_field_none(struct hist_field *field, void *event,
@@ -138,6 +146,13 @@ enum hist_field_flags {
HIST_FIELD_FL_LOG2  = 1 << 9,
HIST_FIELD_FL_TIMESTAMP = 1 << 10,
HIST_FIELD_FL_TIMESTAMP_USECS   = 1 << 11,
+   HIST_FIELD_FL_VAR   = 1 << 12,
+};
+
+struct var_defs {
+   unsigned intn_vars;
+   char*name[TRACING_MAP_VARS_MAX];
+   char*expr[TRACING_MAP_VARS_MAX];
 };
 
 struct hist_trigger_attrs {
@@ -150,13 +165,19 @@ struct hist_trigger_attrs {
boolclear;
boolts_in_usecs;
unsigned intmap_bits;
+
+   char*assignment_str[TRACING_MAP_VARS_MAX];
+   unsigned intn_assignments;
+
+   struct var_defs var_defs;
 };
 
 struct hist_trigger_data {
-   struct hist_field   *fields[TRACING_MAP_FIELDS_MAX];
+   struct hist_field   *fields[HIST_FIELDS_MAX];
unsigned intn_vals;
unsigned intn_keys;
unsigned intn_fields;
+   unsigned intn_vars;
unsigned intkey_size;
struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
unsigned intn_sort_keys;
@@ -164,6 +185,7 @@ struct hist_trigger_data {
struct hist_trigger_attrs   *attrs;
struct tracing_map  *map;
boolenable_timestamps;
+   boolremove;
 };
 
 static u64 hist_field_timestamp(struct hist_field *hist_field, void *event,
@@ -262,9 +284,14 @@ static int parse_map_size(char *str)
 
 static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs)
 {
+   unsigned int i;
+
if (!attrs)
return;
 
+   for (i = 0; i < attrs->n_assignments; i++)
+   kfree(attrs->assignment_str[i]);
+
kfree(attrs->name);
kfree(attrs->sort_key_str);
kfree(attrs->keys_str);
@@ -311,8 +338,22 @@ static int parse_assignment(char *str, struct 
hist_trigger_attrs *attrs)
goto out;
}
attrs->map_bits = map_bits;
-   } else
-   ret = -EINVAL;
+   } else {
+   char *assignment;
+
+   if (attrs->n_assignments == TRACING_MAP_VARS_MAX) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   assignment = kstrdup(str, GFP_KERNEL);
+   if (!assignment) {
+   ret = -ENOMEM;
+   goto