diff options
author | Steven Rostedt <srostedt@redhat.com> | 2011-01-27 22:46:46 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-02-07 20:56:18 -0500 |
commit | 0fc3ca9a10a61a77f18710fb708b41fd99c79a56 (patch) | |
tree | 339fb23a53a54ed9c0f9b9c10344d10cfddd35ea | |
parent | c9c53ca03d6f97fdd9832d5ed3f15b30ee5cdb86 (diff) |
tracing/filter: Call synchronize_sched() just once for system filters
By separating out the reseting of the filter->n_preds to zero from
the reallocation of preds for the filter, we can reset groups of
filters first, call synchronize_sched() just once, and then reallocate
each of the filters in the system group.
Cc: Tom Zanussi <tzanussi@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace_events_filter.c | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index aac6a6183e6a..8f00a11ce778 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -570,17 +570,28 @@ static void __free_preds(struct event_filter *filter) | |||
570 | filter->n_preds = 0; | 570 | filter->n_preds = 0; |
571 | } | 571 | } |
572 | 572 | ||
573 | static void reset_preds(struct event_filter *filter) | ||
574 | { | ||
575 | struct filter_pred *pred; | ||
576 | int n_preds = filter->n_preds; | ||
577 | int i; | ||
578 | |||
579 | filter->n_preds = 0; | ||
580 | if (!filter->preds) | ||
581 | return; | ||
582 | |||
583 | for (i = 0; i < n_preds; i++) { | ||
584 | pred = filter->preds[i]; | ||
585 | pred->fn = filter_pred_none; | ||
586 | } | ||
587 | } | ||
588 | |||
573 | static void filter_disable_preds(struct ftrace_event_call *call) | 589 | static void filter_disable_preds(struct ftrace_event_call *call) |
574 | { | 590 | { |
575 | struct event_filter *filter = call->filter; | 591 | struct event_filter *filter = call->filter; |
576 | int i; | ||
577 | 592 | ||
578 | call->flags &= ~TRACE_EVENT_FL_FILTERED; | 593 | call->flags &= ~TRACE_EVENT_FL_FILTERED; |
579 | if (filter->preds) { | 594 | reset_preds(filter); |
580 | for (i = 0; i < filter->n_preds; i++) | ||
581 | filter->preds[i]->fn = filter_pred_none; | ||
582 | } | ||
583 | filter->n_preds = 0; | ||
584 | } | 595 | } |
585 | 596 | ||
586 | static void __free_filter(struct event_filter *filter) | 597 | static void __free_filter(struct event_filter *filter) |
@@ -620,15 +631,17 @@ static int __alloc_preds(struct event_filter *filter, int n_preds) | |||
620 | 631 | ||
621 | if (filter->preds) { | 632 | if (filter->preds) { |
622 | if (filter->a_preds < n_preds) { | 633 | if (filter->a_preds < n_preds) { |
623 | /* We need to reallocate */ | ||
624 | filter->n_preds = 0; | ||
625 | /* | 634 | /* |
626 | * It is possible that the filter is currently | 635 | * We need to reallocate. |
627 | * being used. We need to zero out the number | 636 | * We should have already have zeroed out |
628 | * of preds, wait on preemption and then free | 637 | * the pred count and called synchronized_sched() |
629 | * the preds. | 638 | * to make sure no one is using the preds. |
630 | */ | 639 | */ |
631 | synchronize_sched(); | 640 | if (WARN_ON_ONCE(filter->n_preds)) { |
641 | /* We need to reset it now */ | ||
642 | filter->n_preds = 0; | ||
643 | synchronize_sched(); | ||
644 | } | ||
632 | __free_preds(filter); | 645 | __free_preds(filter); |
633 | } | 646 | } |
634 | } | 647 | } |
@@ -1328,6 +1341,30 @@ static int replace_system_preds(struct event_subsystem *system, | |||
1328 | /* try to see if the filter can be applied */ | 1341 | /* try to see if the filter can be applied */ |
1329 | err = replace_preds(call, filter, ps, filter_string, true); | 1342 | err = replace_preds(call, filter, ps, filter_string, true); |
1330 | if (err) | 1343 | if (err) |
1344 | goto fail; | ||
1345 | } | ||
1346 | |||
1347 | /* set all filter pred counts to zero */ | ||
1348 | list_for_each_entry(call, &ftrace_events, list) { | ||
1349 | struct event_filter *filter = call->filter; | ||
1350 | |||
1351 | if (strcmp(call->class->system, system->name) != 0) | ||
1352 | continue; | ||
1353 | |||
1354 | reset_preds(filter); | ||
1355 | } | ||
1356 | |||
1357 | /* | ||
1358 | * Since some of the preds may be used under preemption | ||
1359 | * we need to wait for them to finish before we may | ||
1360 | * reallocate them. | ||
1361 | */ | ||
1362 | synchronize_sched(); | ||
1363 | |||
1364 | list_for_each_entry(call, &ftrace_events, list) { | ||
1365 | struct event_filter *filter = call->filter; | ||
1366 | |||
1367 | if (strcmp(call->class->system, system->name) != 0) | ||
1331 | continue; | 1368 | continue; |
1332 | 1369 | ||
1333 | /* really apply the filter */ | 1370 | /* really apply the filter */ |
@@ -1342,11 +1379,13 @@ static int replace_system_preds(struct event_subsystem *system, | |||
1342 | fail = false; | 1379 | fail = false; |
1343 | } | 1380 | } |
1344 | 1381 | ||
1345 | if (fail) { | 1382 | if (fail) |
1346 | parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); | 1383 | goto fail; |
1347 | return -EINVAL; | 1384 | |
1348 | } | ||
1349 | return 0; | 1385 | return 0; |
1386 | fail: | ||
1387 | parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); | ||
1388 | return -EINVAL; | ||
1350 | } | 1389 | } |
1351 | 1390 | ||
1352 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | 1391 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) |
@@ -1381,6 +1420,13 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | |||
1381 | goto out; | 1420 | goto out; |
1382 | } | 1421 | } |
1383 | 1422 | ||
1423 | /* | ||
1424 | * Make sure all the pred counts are zero so that | ||
1425 | * no task is using it when we reallocate the preds array. | ||
1426 | */ | ||
1427 | reset_preds(call->filter); | ||
1428 | synchronize_sched(); | ||
1429 | |||
1384 | err = replace_preds(call, call->filter, ps, filter_string, false); | 1430 | err = replace_preds(call, call->filter, ps, filter_string, false); |
1385 | if (err) | 1431 | if (err) |
1386 | append_filter_err(ps, call->filter); | 1432 | append_filter_err(ps, call->filter); |