summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace.h3
-rw-r--r--kernel/trace/trace_events_hist.c661
-rw-r--r--kernel/trace/trace_events_trigger.c6
4 files changed, 656 insertions, 16 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 82cc8891fda6..68f8702af9fb 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7783,6 +7783,7 @@ static int instance_mkdir(const char *name)
7783 7783
7784 INIT_LIST_HEAD(&tr->systems); 7784 INIT_LIST_HEAD(&tr->systems);
7785 INIT_LIST_HEAD(&tr->events); 7785 INIT_LIST_HEAD(&tr->events);
7786 INIT_LIST_HEAD(&tr->hist_vars);
7786 7787
7787 if (allocate_trace_buffers(tr, trace_buf_size) < 0) 7788 if (allocate_trace_buffers(tr, trace_buf_size) < 0)
7788 goto out_free_tr; 7789 goto out_free_tr;
@@ -8533,6 +8534,7 @@ __init static int tracer_alloc_buffers(void)
8533 8534
8534 INIT_LIST_HEAD(&global_trace.systems); 8535 INIT_LIST_HEAD(&global_trace.systems);
8535 INIT_LIST_HEAD(&global_trace.events); 8536 INIT_LIST_HEAD(&global_trace.events);
8537 INIT_LIST_HEAD(&global_trace.hist_vars);
8536 list_add(&global_trace.list, &ftrace_trace_arrays); 8538 list_add(&global_trace.list, &ftrace_trace_arrays);
8537 8539
8538 apply_trace_boot_options(); 8540 apply_trace_boot_options();
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 89771b4f16df..99b7ee7ed127 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -274,6 +274,7 @@ struct trace_array {
274 int function_enabled; 274 int function_enabled;
275#endif 275#endif
276 int time_stamp_abs_ref; 276 int time_stamp_abs_ref;
277 struct list_head hist_vars;
277}; 278};
278 279
279enum { 280enum {
@@ -1548,6 +1549,8 @@ extern void pause_named_trigger(struct event_trigger_data *data);
1548extern void unpause_named_trigger(struct event_trigger_data *data); 1549extern void unpause_named_trigger(struct event_trigger_data *data);
1549extern void set_named_trigger_data(struct event_trigger_data *data, 1550extern void set_named_trigger_data(struct event_trigger_data *data,
1550 struct event_trigger_data *named_data); 1551 struct event_trigger_data *named_data);
1552extern struct event_trigger_data *
1553get_named_trigger_data(struct event_trigger_data *data);
1551extern int register_event_command(struct event_command *cmd); 1554extern int register_event_command(struct event_command *cmd);
1552extern int unregister_event_command(struct event_command *cmd); 1555extern int unregister_event_command(struct event_command *cmd);
1553extern int register_trigger_hist_enable_disable_cmds(void); 1556extern int register_trigger_hist_enable_disable_cmds(void);
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index e30bd86bee8e..dbcdd2ff76a4 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -59,7 +59,12 @@ struct hist_field {
59 struct hist_trigger_data *hist_data; 59 struct hist_trigger_data *hist_data;
60 struct hist_var var; 60 struct hist_var var;
61 enum field_op_id operator; 61 enum field_op_id operator;
62 char *system;
63 char *event_name;
62 char *name; 64 char *name;
65 unsigned int var_idx;
66 unsigned int var_ref_idx;
67 bool read_once;
63}; 68};
64 69
65static u64 hist_field_none(struct hist_field *field, 70static u64 hist_field_none(struct hist_field *field,
@@ -214,6 +219,7 @@ enum hist_field_flags {
214 HIST_FIELD_FL_TIMESTAMP_USECS = 1 << 11, 219 HIST_FIELD_FL_TIMESTAMP_USECS = 1 << 11,
215 HIST_FIELD_FL_VAR = 1 << 12, 220 HIST_FIELD_FL_VAR = 1 << 12,
216 HIST_FIELD_FL_EXPR = 1 << 13, 221 HIST_FIELD_FL_EXPR = 1 << 13,
222 HIST_FIELD_FL_VAR_REF = 1 << 14,
217}; 223};
218 224
219struct var_defs { 225struct var_defs {
@@ -253,6 +259,8 @@ struct hist_trigger_data {
253 struct tracing_map *map; 259 struct tracing_map *map;
254 bool enable_timestamps; 260 bool enable_timestamps;
255 bool remove; 261 bool remove;
262 struct hist_field *var_refs[TRACING_MAP_VARS_MAX];
263 unsigned int n_var_refs;
256}; 264};
257 265
258static u64 hist_field_timestamp(struct hist_field *hist_field, 266static u64 hist_field_timestamp(struct hist_field *hist_field,
@@ -271,6 +279,214 @@ static u64 hist_field_timestamp(struct hist_field *hist_field,
271 return ts; 279 return ts;
272} 280}
273 281
282struct hist_var_data {
283 struct list_head list;
284 struct hist_trigger_data *hist_data;
285};
286
287static struct hist_field *
288check_field_for_var_ref(struct hist_field *hist_field,
289 struct hist_trigger_data *var_data,
290 unsigned int var_idx)
291{
292 struct hist_field *found = NULL;
293
294 if (hist_field && hist_field->flags & HIST_FIELD_FL_VAR_REF) {
295 if (hist_field->var.idx == var_idx &&
296 hist_field->var.hist_data == var_data) {
297 found = hist_field;
298 }
299 }
300
301 return found;
302}
303
304static struct hist_field *
305check_field_for_var_refs(struct hist_trigger_data *hist_data,
306 struct hist_field *hist_field,
307 struct hist_trigger_data *var_data,
308 unsigned int var_idx,
309 unsigned int level)
310{
311 struct hist_field *found = NULL;
312 unsigned int i;
313
314 if (level > 3)
315 return found;
316
317 if (!hist_field)
318 return found;
319
320 found = check_field_for_var_ref(hist_field, var_data, var_idx);
321 if (found)
322 return found;
323
324 for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++) {
325 struct hist_field *operand;
326
327 operand = hist_field->operands[i];
328 found = check_field_for_var_refs(hist_data, operand, var_data,
329 var_idx, level + 1);
330 if (found)
331 return found;
332 }
333
334 return found;
335}
336
337static struct hist_field *find_var_ref(struct hist_trigger_data *hist_data,
338 struct hist_trigger_data *var_data,
339 unsigned int var_idx)
340{
341 struct hist_field *hist_field, *found = NULL;
342 unsigned int i;
343
344 for_each_hist_field(i, hist_data) {
345 hist_field = hist_data->fields[i];
346 found = check_field_for_var_refs(hist_data, hist_field,
347 var_data, var_idx, 0);
348 if (found)
349 return found;
350 }
351
352 return found;
353}
354
355static struct hist_field *find_any_var_ref(struct hist_trigger_data *hist_data,
356 unsigned int var_idx)
357{
358 struct trace_array *tr = hist_data->event_file->tr;
359 struct hist_field *found = NULL;
360 struct hist_var_data *var_data;
361
362 list_for_each_entry(var_data, &tr->hist_vars, list) {
363 if (var_data->hist_data == hist_data)
364 continue;
365 found = find_var_ref(var_data->hist_data, hist_data, var_idx);
366 if (found)
367 break;
368 }
369
370 return found;
371}
372
373static bool check_var_refs(struct hist_trigger_data *hist_data)
374{
375 struct hist_field *field;
376 bool found = false;
377 int i;
378
379 for_each_hist_field(i, hist_data) {
380 field = hist_data->fields[i];
381 if (field && field->flags & HIST_FIELD_FL_VAR) {
382 if (find_any_var_ref(hist_data, field->var.idx)) {
383 found = true;
384 break;
385 }
386 }
387 }
388
389 return found;
390}
391
392static struct hist_var_data *find_hist_vars(struct hist_trigger_data *hist_data)
393{
394 struct trace_array *tr = hist_data->event_file->tr;
395 struct hist_var_data *var_data, *found = NULL;
396
397 list_for_each_entry(var_data, &tr->hist_vars, list) {
398 if (var_data->hist_data == hist_data) {
399 found = var_data;
400 break;
401 }
402 }
403
404 return found;
405}
406
407static bool field_has_hist_vars(struct hist_field *hist_field,
408 unsigned int level)
409{
410 int i;
411
412 if (level > 3)
413 return false;
414
415 if (!hist_field)
416 return false;
417
418 if (hist_field->flags & HIST_FIELD_FL_VAR ||
419 hist_field->flags & HIST_FIELD_FL_VAR_REF)
420 return true;
421
422 for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++) {
423 struct hist_field *operand;
424
425 operand = hist_field->operands[i];
426 if (field_has_hist_vars(operand, level + 1))
427 return true;
428 }
429
430 return false;
431}
432
433static bool has_hist_vars(struct hist_trigger_data *hist_data)
434{
435 struct hist_field *hist_field;
436 int i;
437
438 for_each_hist_field(i, hist_data) {
439 hist_field = hist_data->fields[i];
440 if (field_has_hist_vars(hist_field, 0))
441 return true;
442 }
443
444 return false;
445}
446
447static int save_hist_vars(struct hist_trigger_data *hist_data)
448{
449 struct trace_array *tr = hist_data->event_file->tr;
450 struct hist_var_data *var_data;
451
452 var_data = find_hist_vars(hist_data);
453 if (var_data)
454 return 0;
455
456 if (trace_array_get(tr) < 0)
457 return -ENODEV;
458
459 var_data = kzalloc(sizeof(*var_data), GFP_KERNEL);
460 if (!var_data) {
461 trace_array_put(tr);
462 return -ENOMEM;
463 }
464
465 var_data->hist_data = hist_data;
466 list_add(&var_data->list, &tr->hist_vars);
467
468 return 0;
469}
470
471static void remove_hist_vars(struct hist_trigger_data *hist_data)
472{
473 struct trace_array *tr = hist_data->event_file->tr;
474 struct hist_var_data *var_data;
475
476 var_data = find_hist_vars(hist_data);
477 if (!var_data)
478 return;
479
480 if (WARN_ON(check_var_refs(hist_data)))
481 return;
482
483 list_del(&var_data->list);
484
485 kfree(var_data);
486
487 trace_array_put(tr);
488}
489
274static struct hist_field *find_var_field(struct hist_trigger_data *hist_data, 490static struct hist_field *find_var_field(struct hist_trigger_data *hist_data,
275 const char *var_name) 491 const char *var_name)
276{ 492{
@@ -313,10 +529,137 @@ static struct hist_field *find_var(struct hist_trigger_data *hist_data,
313 return NULL; 529 return NULL;
314} 530}
315 531
532static struct trace_event_file *find_var_file(struct trace_array *tr,
533 char *system,
534 char *event_name,
535 char *var_name)
536{
537 struct hist_trigger_data *var_hist_data;
538 struct hist_var_data *var_data;
539 struct trace_event_file *file, *found = NULL;
540
541 if (system)
542 return find_event_file(tr, system, event_name);
543
544 list_for_each_entry(var_data, &tr->hist_vars, list) {
545 var_hist_data = var_data->hist_data;
546 file = var_hist_data->event_file;
547 if (file == found)
548 continue;
549
550 if (find_var_field(var_hist_data, var_name)) {
551 if (found)
552 return NULL;
553
554 found = file;
555 }
556 }
557
558 return found;
559}
560
561static struct hist_field *find_file_var(struct trace_event_file *file,
562 const char *var_name)
563{
564 struct hist_trigger_data *test_data;
565 struct event_trigger_data *test;
566 struct hist_field *hist_field;
567
568 list_for_each_entry_rcu(test, &file->triggers, list) {
569 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
570 test_data = test->private_data;
571 hist_field = find_var_field(test_data, var_name);
572 if (hist_field)
573 return hist_field;
574 }
575 }
576
577 return NULL;
578}
579
580static struct hist_field *find_event_var(struct hist_trigger_data *hist_data,
581 char *system,
582 char *event_name,
583 char *var_name)
584{
585 struct trace_array *tr = hist_data->event_file->tr;
586 struct hist_field *hist_field = NULL;
587 struct trace_event_file *file;
588
589 file = find_var_file(tr, system, event_name, var_name);
590 if (!file)
591 return NULL;
592
593 hist_field = find_file_var(file, var_name);
594
595 return hist_field;
596}
597
316struct hist_elt_data { 598struct hist_elt_data {
317 char *comm; 599 char *comm;
600 u64 *var_ref_vals;
318}; 601};
319 602
603static u64 hist_field_var_ref(struct hist_field *hist_field,
604 struct tracing_map_elt *elt,
605 struct ring_buffer_event *rbe,
606 void *event)
607{
608 struct hist_elt_data *elt_data;
609 u64 var_val = 0;
610
611 elt_data = elt->private_data;
612 var_val = elt_data->var_ref_vals[hist_field->var_ref_idx];
613
614 return var_val;
615}
616
617static bool resolve_var_refs(struct hist_trigger_data *hist_data, void *key,
618 u64 *var_ref_vals, bool self)
619{
620 struct hist_trigger_data *var_data;
621 struct tracing_map_elt *var_elt;
622 struct hist_field *hist_field;
623 unsigned int i, var_idx;
624 bool resolved = true;
625 u64 var_val = 0;
626
627 for (i = 0; i < hist_data->n_var_refs; i++) {
628 hist_field = hist_data->var_refs[i];
629 var_idx = hist_field->var.idx;
630 var_data = hist_field->var.hist_data;
631
632 if (var_data == NULL) {
633 resolved = false;
634 break;
635 }
636
637 if ((self && var_data != hist_data) ||
638 (!self && var_data == hist_data))
639 continue;
640
641 var_elt = tracing_map_lookup(var_data->map, key);
642 if (!var_elt) {
643 resolved = false;
644 break;
645 }
646
647 if (!tracing_map_var_set(var_elt, var_idx)) {
648 resolved = false;
649 break;
650 }
651
652 if (self || !hist_field->read_once)
653 var_val = tracing_map_read_var(var_elt, var_idx);
654 else
655 var_val = tracing_map_read_var_once(var_elt, var_idx);
656
657 var_ref_vals[i] = var_val;
658 }
659
660 return resolved;
661}
662
320static const char *hist_field_name(struct hist_field *field, 663static const char *hist_field_name(struct hist_field *field,
321 unsigned int level) 664 unsigned int level)
322{ 665{
@@ -331,8 +674,20 @@ static const char *hist_field_name(struct hist_field *field,
331 field_name = hist_field_name(field->operands[0], ++level); 674 field_name = hist_field_name(field->operands[0], ++level);
332 else if (field->flags & HIST_FIELD_FL_TIMESTAMP) 675 else if (field->flags & HIST_FIELD_FL_TIMESTAMP)
333 field_name = "common_timestamp"; 676 field_name = "common_timestamp";
334 else if (field->flags & HIST_FIELD_FL_EXPR) 677 else if (field->flags & HIST_FIELD_FL_EXPR ||
335 field_name = field->name; 678 field->flags & HIST_FIELD_FL_VAR_REF) {
679 if (field->system) {
680 static char full_name[MAX_FILTER_STR_VAL];
681
682 strcat(full_name, field->system);
683 strcat(full_name, ".");
684 strcat(full_name, field->event_name);
685 strcat(full_name, ".");
686 strcat(full_name, field->name);
687 field_name = full_name;
688 } else
689 field_name = field->name;
690 }
336 691
337 if (field_name == NULL) 692 if (field_name == NULL)
338 field_name = ""; 693 field_name = "";
@@ -612,6 +967,9 @@ static const char *get_hist_field_flags(struct hist_field *hist_field)
612 967
613static void expr_field_str(struct hist_field *field, char *expr) 968static void expr_field_str(struct hist_field *field, char *expr)
614{ 969{
970 if (field->flags & HIST_FIELD_FL_VAR_REF)
971 strcat(expr, "$");
972
615 strcat(expr, hist_field_name(field, 0)); 973 strcat(expr, hist_field_name(field, 0));
616 974
617 if (field->flags) { 975 if (field->flags) {
@@ -742,6 +1100,11 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
742 if (flags & HIST_FIELD_FL_EXPR) 1100 if (flags & HIST_FIELD_FL_EXPR)
743 goto out; /* caller will populate */ 1101 goto out; /* caller will populate */
744 1102
1103 if (flags & HIST_FIELD_FL_VAR_REF) {
1104 hist_field->fn = hist_field_var_ref;
1105 goto out;
1106 }
1107
745 if (flags & HIST_FIELD_FL_HITCOUNT) { 1108 if (flags & HIST_FIELD_FL_HITCOUNT) {
746 hist_field->fn = hist_field_counter; 1109 hist_field->fn = hist_field_counter;
747 hist_field->size = sizeof(u64); 1110 hist_field->size = sizeof(u64);
@@ -835,6 +1198,144 @@ static void destroy_hist_fields(struct hist_trigger_data *hist_data)
835 } 1198 }
836} 1199}
837 1200
1201static int init_var_ref(struct hist_field *ref_field,
1202 struct hist_field *var_field,
1203 char *system, char *event_name)
1204{
1205 int err = 0;
1206
1207 ref_field->var.idx = var_field->var.idx;
1208 ref_field->var.hist_data = var_field->hist_data;
1209 ref_field->size = var_field->size;
1210 ref_field->is_signed = var_field->is_signed;
1211 ref_field->flags |= var_field->flags &
1212 (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
1213
1214 if (system) {
1215 ref_field->system = kstrdup(system, GFP_KERNEL);
1216 if (!ref_field->system)
1217 return -ENOMEM;
1218 }
1219
1220 if (event_name) {
1221 ref_field->event_name = kstrdup(event_name, GFP_KERNEL);
1222 if (!ref_field->event_name) {
1223 err = -ENOMEM;
1224 goto free;
1225 }
1226 }
1227
1228 ref_field->name = kstrdup(var_field->var.name, GFP_KERNEL);
1229 if (!ref_field->name) {
1230 err = -ENOMEM;
1231 goto free;
1232 }
1233
1234 ref_field->type = kstrdup(var_field->type, GFP_KERNEL);
1235 if (!ref_field->type) {
1236 err = -ENOMEM;
1237 goto free;
1238 }
1239 out:
1240 return err;
1241 free:
1242 kfree(ref_field->system);
1243 kfree(ref_field->event_name);
1244 kfree(ref_field->name);
1245
1246 goto out;
1247}
1248
1249static struct hist_field *create_var_ref(struct hist_field *var_field,
1250 char *system, char *event_name)
1251{
1252 unsigned long flags = HIST_FIELD_FL_VAR_REF;
1253 struct hist_field *ref_field;
1254
1255 ref_field = create_hist_field(var_field->hist_data, NULL, flags, NULL);
1256 if (ref_field) {
1257 if (init_var_ref(ref_field, var_field, system, event_name)) {
1258 destroy_hist_field(ref_field, 0);
1259 return NULL;
1260 }
1261 }
1262
1263 return ref_field;
1264}
1265
1266static bool is_var_ref(char *var_name)
1267{
1268 if (!var_name || strlen(var_name) < 2 || var_name[0] != '$')
1269 return false;
1270
1271 return true;
1272}
1273
1274static char *field_name_from_var(struct hist_trigger_data *hist_data,
1275 char *var_name)
1276{
1277 char *name, *field;
1278 unsigned int i;
1279
1280 for (i = 0; i < hist_data->attrs->var_defs.n_vars; i++) {
1281 name = hist_data->attrs->var_defs.name[i];
1282
1283 if (strcmp(var_name, name) == 0) {
1284 field = hist_data->attrs->var_defs.expr[i];
1285 if (contains_operator(field) || is_var_ref(field))
1286 continue;
1287 return field;
1288 }
1289 }
1290
1291 return NULL;
1292}
1293
1294static char *local_field_var_ref(struct hist_trigger_data *hist_data,
1295 char *system, char *event_name,
1296 char *var_name)
1297{
1298 struct trace_event_call *call;
1299
1300 if (system && event_name) {
1301 call = hist_data->event_file->event_call;
1302
1303 if (strcmp(system, call->class->system) != 0)
1304 return NULL;
1305
1306 if (strcmp(event_name, trace_event_name(call)) != 0)
1307 return NULL;
1308 }
1309
1310 if (!!system != !!event_name)
1311 return NULL;
1312
1313 if (!is_var_ref(var_name))
1314 return NULL;
1315
1316 var_name++;
1317
1318 return field_name_from_var(hist_data, var_name);
1319}
1320
1321static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data,
1322 char *system, char *event_name,
1323 char *var_name)
1324{
1325 struct hist_field *var_field = NULL, *ref_field = NULL;
1326
1327 if (!is_var_ref(var_name))
1328 return NULL;
1329
1330 var_name++;
1331
1332 var_field = find_event_var(hist_data, system, event_name, var_name);
1333 if (var_field)
1334 ref_field = create_var_ref(var_field, system, event_name);
1335
1336 return ref_field;
1337}
1338
838static struct ftrace_event_field * 1339static struct ftrace_event_field *
839parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file, 1340parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
840 char *field_str, unsigned long *flags) 1341 char *field_str, unsigned long *flags)
@@ -891,10 +1392,40 @@ static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
891 struct trace_event_file *file, char *str, 1392 struct trace_event_file *file, char *str,
892 unsigned long *flags, char *var_name) 1393 unsigned long *flags, char *var_name)
893{ 1394{
1395 char *s, *ref_system = NULL, *ref_event = NULL, *ref_var = str;
894 struct ftrace_event_field *field = NULL; 1396 struct ftrace_event_field *field = NULL;
895 struct hist_field *hist_field = NULL; 1397 struct hist_field *hist_field = NULL;
896 int ret = 0; 1398 int ret = 0;
897 1399
1400 s = strchr(str, '.');
1401 if (s) {
1402 s = strchr(++s, '.');
1403 if (s) {
1404 ref_system = strsep(&str, ".");
1405 if (!str) {
1406 ret = -EINVAL;
1407 goto out;
1408 }
1409 ref_event = strsep(&str, ".");
1410 if (!str) {
1411 ret = -EINVAL;
1412 goto out;
1413 }
1414 ref_var = str;
1415 }
1416 }
1417
1418 s = local_field_var_ref(hist_data, ref_system, ref_event, ref_var);
1419 if (!s) {
1420 hist_field = parse_var_ref(hist_data, ref_system, ref_event, ref_var);
1421 if (hist_field) {
1422 hist_data->var_refs[hist_data->n_var_refs] = hist_field;
1423 hist_field->var_ref_idx = hist_data->n_var_refs++;
1424 return hist_field;
1425 }
1426 } else
1427 str = s;
1428
898 field = parse_field(hist_data, file, str, flags); 1429 field = parse_field(hist_data, file, str, flags);
899 if (IS_ERR(field)) { 1430 if (IS_ERR(field)) {
900 ret = PTR_ERR(field); 1431 ret = PTR_ERR(field);
@@ -1066,6 +1597,9 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
1066 goto free; 1597 goto free;
1067 } 1598 }
1068 1599
1600 operand1->read_once = true;
1601 operand2->read_once = true;
1602
1069 expr->operands[0] = operand1; 1603 expr->operands[0] = operand1;
1070 expr->operands[1] = operand2; 1604 expr->operands[1] = operand2;
1071 expr->operator = field_op; 1605 expr->operator = field_op;
@@ -1238,6 +1772,12 @@ static int create_key_field(struct hist_trigger_data *hist_data,
1238 goto out; 1772 goto out;
1239 } 1773 }
1240 1774
1775 if (hist_field->flags & HIST_FIELD_FL_VAR_REF) {
1776 destroy_hist_field(hist_field, 0);
1777 ret = -EINVAL;
1778 goto out;
1779 }
1780
1241 key_size = hist_field->size; 1781 key_size = hist_field->size;
1242 } 1782 }
1243 1783
@@ -1576,6 +2116,7 @@ create_hist_data(unsigned int map_bits,
1576 2116
1577 hist_data->attrs = attrs; 2117 hist_data->attrs = attrs;
1578 hist_data->remove = remove; 2118 hist_data->remove = remove;
2119 hist_data->event_file = file;
1579 2120
1580 ret = create_hist_fields(hist_data, file); 2121 ret = create_hist_fields(hist_data, file);
1581 if (ret) 2122 if (ret)
@@ -1598,12 +2139,6 @@ create_hist_data(unsigned int map_bits,
1598 ret = create_tracing_map_fields(hist_data); 2139 ret = create_tracing_map_fields(hist_data);
1599 if (ret) 2140 if (ret)
1600 goto free; 2141 goto free;
1601
1602 ret = tracing_map_init(hist_data->map);
1603 if (ret)
1604 goto free;
1605
1606 hist_data->event_file = file;
1607 out: 2142 out:
1608 return hist_data; 2143 return hist_data;
1609 free: 2144 free:
@@ -1618,12 +2153,17 @@ create_hist_data(unsigned int map_bits,
1618 2153
1619static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, 2154static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
1620 struct tracing_map_elt *elt, void *rec, 2155 struct tracing_map_elt *elt, void *rec,
1621 struct ring_buffer_event *rbe) 2156 struct ring_buffer_event *rbe,
2157 u64 *var_ref_vals)
1622{ 2158{
2159 struct hist_elt_data *elt_data;
1623 struct hist_field *hist_field; 2160 struct hist_field *hist_field;
1624 unsigned int i, var_idx; 2161 unsigned int i, var_idx;
1625 u64 hist_val; 2162 u64 hist_val;
1626 2163
2164 elt_data = elt->private_data;
2165 elt_data->var_ref_vals = var_ref_vals;
2166
1627 for_each_hist_val_field(i, hist_data) { 2167 for_each_hist_val_field(i, hist_data) {
1628 hist_field = hist_data->fields[i]; 2168 hist_field = hist_data->fields[i];
1629 hist_val = hist_field->fn(hist_field, elt, rbe, rec); 2169 hist_val = hist_field->fn(hist_field, elt, rbe, rec);
@@ -1675,6 +2215,7 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec,
1675 struct hist_trigger_data *hist_data = data->private_data; 2215 struct hist_trigger_data *hist_data = data->private_data;
1676 bool use_compound_key = (hist_data->n_keys > 1); 2216 bool use_compound_key = (hist_data->n_keys > 1);
1677 unsigned long entries[HIST_STACKTRACE_DEPTH]; 2217 unsigned long entries[HIST_STACKTRACE_DEPTH];
2218 u64 var_ref_vals[TRACING_MAP_VARS_MAX];
1678 char compound_key[HIST_KEY_SIZE_MAX]; 2219 char compound_key[HIST_KEY_SIZE_MAX];
1679 struct tracing_map_elt *elt = NULL; 2220 struct tracing_map_elt *elt = NULL;
1680 struct stack_trace stacktrace; 2221 struct stack_trace stacktrace;
@@ -1714,9 +2255,15 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec,
1714 if (use_compound_key) 2255 if (use_compound_key)
1715 key = compound_key; 2256 key = compound_key;
1716 2257
2258 if (hist_data->n_var_refs &&
2259 !resolve_var_refs(hist_data, key, var_ref_vals, false))
2260 return;
2261
1717 elt = tracing_map_insert(hist_data->map, key); 2262 elt = tracing_map_insert(hist_data->map, key);
1718 if (elt) 2263 if (!elt)
1719 hist_trigger_elt_update(hist_data, elt, rec, rbe); 2264 return;
2265
2266 hist_trigger_elt_update(hist_data, elt, rec, rbe, var_ref_vals);
1720} 2267}
1721 2268
1722static void hist_trigger_stacktrace_print(struct seq_file *m, 2269static void hist_trigger_stacktrace_print(struct seq_file *m,
@@ -1931,8 +2478,11 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
1931 2478
1932 if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP) 2479 if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP)
1933 seq_puts(m, "common_timestamp"); 2480 seq_puts(m, "common_timestamp");
1934 else if (field_name) 2481 else if (field_name) {
2482 if (hist_field->flags & HIST_FIELD_FL_VAR_REF)
2483 seq_putc(m, '$');
1935 seq_printf(m, "%s", field_name); 2484 seq_printf(m, "%s", field_name);
2485 }
1936 2486
1937 if (hist_field->flags) { 2487 if (hist_field->flags) {
1938 const char *flags_str = get_hist_field_flags(hist_field); 2488 const char *flags_str = get_hist_field_flags(hist_field);
@@ -2072,7 +2622,11 @@ static void event_hist_trigger_free(struct event_trigger_ops *ops,
2072 if (!data->ref) { 2622 if (!data->ref) {
2073 if (data->name) 2623 if (data->name)
2074 del_named_trigger(data); 2624 del_named_trigger(data);
2625
2075 trigger_data_free(data); 2626 trigger_data_free(data);
2627
2628 remove_hist_vars(hist_data);
2629
2076 destroy_hist_data(hist_data); 2630 destroy_hist_data(hist_data);
2077 } 2631 }
2078} 2632}
@@ -2285,23 +2839,55 @@ static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
2285 goto out; 2839 goto out;
2286 } 2840 }
2287 2841
2288 list_add_rcu(&data->list, &file->triggers);
2289 ret++; 2842 ret++;
2290 2843
2291 update_cond_flag(file);
2292
2293 if (hist_data->enable_timestamps) 2844 if (hist_data->enable_timestamps)
2294 tracing_set_time_stamp_abs(file->tr, true); 2845 tracing_set_time_stamp_abs(file->tr, true);
2846 out:
2847 return ret;
2848}
2849
2850static int hist_trigger_enable(struct event_trigger_data *data,
2851 struct trace_event_file *file)
2852{
2853 int ret = 0;
2854
2855 list_add_tail_rcu(&data->list, &file->triggers);
2856
2857 update_cond_flag(file);
2295 2858
2296 if (trace_event_trigger_enable_disable(file, 1) < 0) { 2859 if (trace_event_trigger_enable_disable(file, 1) < 0) {
2297 list_del_rcu(&data->list); 2860 list_del_rcu(&data->list);
2298 update_cond_flag(file); 2861 update_cond_flag(file);
2299 ret--; 2862 ret--;
2300 } 2863 }
2301 out: 2864
2302 return ret; 2865 return ret;
2303} 2866}
2304 2867
2868static bool hist_trigger_check_refs(struct event_trigger_data *data,
2869 struct trace_event_file *file)
2870{
2871 struct hist_trigger_data *hist_data = data->private_data;
2872 struct event_trigger_data *test, *named_data = NULL;
2873
2874 if (hist_data->attrs->name)
2875 named_data = find_named_trigger(hist_data->attrs->name);
2876
2877 list_for_each_entry_rcu(test, &file->triggers, list) {
2878 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
2879 if (!hist_trigger_match(data, test, named_data, false))
2880 continue;
2881 hist_data = test->private_data;
2882 if (check_var_refs(hist_data))
2883 return true;
2884 break;
2885 }
2886 }
2887
2888 return false;
2889}
2890
2305static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops, 2891static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops,
2306 struct event_trigger_data *data, 2892 struct event_trigger_data *data,
2307 struct trace_event_file *file) 2893 struct trace_event_file *file)
@@ -2334,11 +2920,30 @@ static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops,
2334 } 2920 }
2335} 2921}
2336 2922
2923static bool hist_file_check_refs(struct trace_event_file *file)
2924{
2925 struct hist_trigger_data *hist_data;
2926 struct event_trigger_data *test;
2927
2928 list_for_each_entry_rcu(test, &file->triggers, list) {
2929 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
2930 hist_data = test->private_data;
2931 if (check_var_refs(hist_data))
2932 return true;
2933 }
2934 }
2935
2936 return false;
2937}
2938
2337static void hist_unreg_all(struct trace_event_file *file) 2939static void hist_unreg_all(struct trace_event_file *file)
2338{ 2940{
2339 struct event_trigger_data *test, *n; 2941 struct event_trigger_data *test, *n;
2340 struct hist_trigger_data *hist_data; 2942 struct hist_trigger_data *hist_data;
2341 2943
2944 if (hist_file_check_refs(file))
2945 return;
2946
2342 list_for_each_entry_safe(test, n, &file->triggers, list) { 2947 list_for_each_entry_safe(test, n, &file->triggers, list) {
2343 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { 2948 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
2344 hist_data = test->private_data; 2949 hist_data = test->private_data;
@@ -2414,6 +3019,11 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
2414 } 3019 }
2415 3020
2416 if (remove) { 3021 if (remove) {
3022 if (hist_trigger_check_refs(trigger_data, file)) {
3023 ret = -EBUSY;
3024 goto out_free;
3025 }
3026
2417 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file); 3027 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file);
2418 ret = 0; 3028 ret = 0;
2419 goto out_free; 3029 goto out_free;
@@ -2431,14 +3041,33 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
2431 goto out_free; 3041 goto out_free;
2432 } else if (ret < 0) 3042 } else if (ret < 0)
2433 goto out_free; 3043 goto out_free;
3044
3045 if (get_named_trigger_data(trigger_data))
3046 goto enable;
3047
3048 if (has_hist_vars(hist_data))
3049 save_hist_vars(hist_data);
3050
3051 ret = tracing_map_init(hist_data->map);
3052 if (ret)
3053 goto out_unreg;
3054enable:
3055 ret = hist_trigger_enable(trigger_data, file);
3056 if (ret)
3057 goto out_unreg;
3058
2434 /* Just return zero, not the number of registered triggers */ 3059 /* Just return zero, not the number of registered triggers */
2435 ret = 0; 3060 ret = 0;
2436 out: 3061 out:
2437 return ret; 3062 return ret;
3063 out_unreg:
3064 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file);
2438 out_free: 3065 out_free:
2439 if (cmd_ops->set_filter) 3066 if (cmd_ops->set_filter)
2440 cmd_ops->set_filter(NULL, trigger_data, NULL); 3067 cmd_ops->set_filter(NULL, trigger_data, NULL);
2441 3068
3069 remove_hist_vars(hist_data);
3070
2442 kfree(trigger_data); 3071 kfree(trigger_data);
2443 3072
2444 destroy_hist_data(hist_data); 3073 destroy_hist_data(hist_data);
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
index 632471692462..d251cabcf69a 100644
--- a/kernel/trace/trace_events_trigger.c
+++ b/kernel/trace/trace_events_trigger.c
@@ -909,6 +909,12 @@ void set_named_trigger_data(struct event_trigger_data *data,
909 data->named_data = named_data; 909 data->named_data = named_data;
910} 910}
911 911
912struct event_trigger_data *
913get_named_trigger_data(struct event_trigger_data *data)
914{
915 return data->named_data;
916}
917
912static void 918static void
913traceon_trigger(struct event_trigger_data *data, void *rec, 919traceon_trigger(struct event_trigger_data *data, void *rec,
914 struct ring_buffer_event *event) 920 struct ring_buffer_event *event)