aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-01-27 22:46:46 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-02-07 20:56:18 -0500
commit0fc3ca9a10a61a77f18710fb708b41fd99c79a56 (patch)
tree339fb23a53a54ed9c0f9b9c10344d10cfddd35ea /kernel/trace
parentc9c53ca03d6f97fdd9832d5ed3f15b30ee5cdb86 (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>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_events_filter.c80
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
573static 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
573static void filter_disable_preds(struct ftrace_event_call *call) 589static 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
586static void __free_filter(struct event_filter *filter) 597static 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
1352int apply_event_filter(struct ftrace_event_call *call, char *filter_string) 1391int 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);