diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2011-03-02 10:09:55 -0500 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2011-03-02 22:29:25 -0500 |
| commit | c09d7a3d2e365e11c09b9c6414c17fe55bd32a8e (patch) | |
| tree | 8823dc4ba7ab25af71a0df8187ea800f0123aeff /kernel/trace | |
| parent | 0a10247914a5cad3caf7ef8a255c54c4d3ed2062 (diff) | |
| parent | 4defe682d81a4960b6840ee4ed1a36f9db77c7bd (diff) | |
Merge branch '/tip/perf/filter' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace.git into perf/core
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace.h | 38 | ||||
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 885 |
2 files changed, 754 insertions, 169 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 9021f8c0c0c..856e73cc1d3 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -661,8 +661,10 @@ struct ftrace_event_field { | |||
| 661 | }; | 661 | }; |
| 662 | 662 | ||
| 663 | struct event_filter { | 663 | struct event_filter { |
| 664 | int n_preds; | 664 | int n_preds; /* Number assigned */ |
| 665 | struct filter_pred **preds; | 665 | int a_preds; /* allocated */ |
| 666 | struct filter_pred *preds; | ||
| 667 | struct filter_pred *root; | ||
| 666 | char *filter_string; | 668 | char *filter_string; |
| 667 | }; | 669 | }; |
| 668 | 670 | ||
| @@ -674,11 +676,23 @@ struct event_subsystem { | |||
| 674 | int nr_events; | 676 | int nr_events; |
| 675 | }; | 677 | }; |
| 676 | 678 | ||
| 679 | #define FILTER_PRED_INVALID ((unsigned short)-1) | ||
| 680 | #define FILTER_PRED_IS_RIGHT (1 << 15) | ||
| 681 | #define FILTER_PRED_FOLD (1 << 15) | ||
| 682 | |||
| 683 | /* | ||
| 684 | * The max preds is the size of unsigned short with | ||
| 685 | * two flags at the MSBs. One bit is used for both the IS_RIGHT | ||
| 686 | * and FOLD flags. The other is reserved. | ||
| 687 | * | ||
| 688 | * 2^14 preds is way more than enough. | ||
| 689 | */ | ||
| 690 | #define MAX_FILTER_PRED 16384 | ||
| 691 | |||
| 677 | struct filter_pred; | 692 | struct filter_pred; |
| 678 | struct regex; | 693 | struct regex; |
| 679 | 694 | ||
| 680 | typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, | 695 | typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event); |
| 681 | int val1, int val2); | ||
| 682 | 696 | ||
| 683 | typedef int (*regex_match_func)(char *str, struct regex *r, int len); | 697 | typedef int (*regex_match_func)(char *str, struct regex *r, int len); |
| 684 | 698 | ||
| @@ -700,11 +714,23 @@ struct filter_pred { | |||
| 700 | filter_pred_fn_t fn; | 714 | filter_pred_fn_t fn; |
| 701 | u64 val; | 715 | u64 val; |
| 702 | struct regex regex; | 716 | struct regex regex; |
| 703 | char *field_name; | 717 | /* |
| 718 | * Leaf nodes use field_name, ops is used by AND and OR | ||
| 719 | * nodes. The field_name is always freed when freeing a pred. | ||
| 720 | * We can overload field_name for ops and have it freed | ||
| 721 | * as well. | ||
| 722 | */ | ||
| 723 | union { | ||
| 724 | char *field_name; | ||
| 725 | unsigned short *ops; | ||
| 726 | }; | ||
| 704 | int offset; | 727 | int offset; |
| 705 | int not; | 728 | int not; |
| 706 | int op; | 729 | int op; |
| 707 | int pop_n; | 730 | unsigned short index; |
| 731 | unsigned short parent; | ||
| 732 | unsigned short left; | ||
| 733 | unsigned short right; | ||
| 708 | }; | 734 | }; |
| 709 | 735 | ||
| 710 | extern struct list_head ftrace_common_fields; | 736 | extern struct list_head ftrace_common_fields; |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 36d40104b17..3249b4f77ef 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
| @@ -123,9 +123,13 @@ struct filter_parse_state { | |||
| 123 | } operand; | 123 | } operand; |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | struct pred_stack { | ||
| 127 | struct filter_pred **preds; | ||
| 128 | int index; | ||
| 129 | }; | ||
| 130 | |||
| 126 | #define DEFINE_COMPARISON_PRED(type) \ | 131 | #define DEFINE_COMPARISON_PRED(type) \ |
| 127 | static int filter_pred_##type(struct filter_pred *pred, void *event, \ | 132 | static int filter_pred_##type(struct filter_pred *pred, void *event) \ |
| 128 | int val1, int val2) \ | ||
| 129 | { \ | 133 | { \ |
| 130 | type *addr = (type *)(event + pred->offset); \ | 134 | type *addr = (type *)(event + pred->offset); \ |
| 131 | type val = (type)pred->val; \ | 135 | type val = (type)pred->val; \ |
| @@ -152,8 +156,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event, \ | |||
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | #define DEFINE_EQUALITY_PRED(size) \ | 158 | #define DEFINE_EQUALITY_PRED(size) \ |
| 155 | static int filter_pred_##size(struct filter_pred *pred, void *event, \ | 159 | static int filter_pred_##size(struct filter_pred *pred, void *event) \ |
| 156 | int val1, int val2) \ | ||
| 157 | { \ | 160 | { \ |
| 158 | u##size *addr = (u##size *)(event + pred->offset); \ | 161 | u##size *addr = (u##size *)(event + pred->offset); \ |
| 159 | u##size val = (u##size)pred->val; \ | 162 | u##size val = (u##size)pred->val; \ |
| @@ -178,23 +181,8 @@ DEFINE_EQUALITY_PRED(32); | |||
| 178 | DEFINE_EQUALITY_PRED(16); | 181 | DEFINE_EQUALITY_PRED(16); |
| 179 | DEFINE_EQUALITY_PRED(8); | 182 | DEFINE_EQUALITY_PRED(8); |
| 180 | 183 | ||
| 181 | static int filter_pred_and(struct filter_pred *pred __attribute((unused)), | ||
| 182 | void *event __attribute((unused)), | ||
| 183 | int val1, int val2) | ||
| 184 | { | ||
| 185 | return val1 && val2; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int filter_pred_or(struct filter_pred *pred __attribute((unused)), | ||
| 189 | void *event __attribute((unused)), | ||
| 190 | int val1, int val2) | ||
| 191 | { | ||
| 192 | return val1 || val2; | ||
| 193 | } | ||
| 194 | |||
| 195 | /* Filter predicate for fixed sized arrays of characters */ | 184 | /* Filter predicate for fixed sized arrays of characters */ |
| 196 | static int filter_pred_string(struct filter_pred *pred, void *event, | 185 | static int filter_pred_string(struct filter_pred *pred, void *event) |
| 197 | int val1, int val2) | ||
| 198 | { | 186 | { |
| 199 | char *addr = (char *)(event + pred->offset); | 187 | char *addr = (char *)(event + pred->offset); |
| 200 | int cmp, match; | 188 | int cmp, match; |
| @@ -207,8 +195,7 @@ static int filter_pred_string(struct filter_pred *pred, void *event, | |||
| 207 | } | 195 | } |
| 208 | 196 | ||
| 209 | /* Filter predicate for char * pointers */ | 197 | /* Filter predicate for char * pointers */ |
| 210 | static int filter_pred_pchar(struct filter_pred *pred, void *event, | 198 | static int filter_pred_pchar(struct filter_pred *pred, void *event) |
| 211 | int val1, int val2) | ||
| 212 | { | 199 | { |
| 213 | char **addr = (char **)(event + pred->offset); | 200 | char **addr = (char **)(event + pred->offset); |
| 214 | int cmp, match; | 201 | int cmp, match; |
| @@ -231,8 +218,7 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event, | |||
| 231 | * and add it to the address of the entry, and at last we have | 218 | * and add it to the address of the entry, and at last we have |
| 232 | * the address of the string. | 219 | * the address of the string. |
| 233 | */ | 220 | */ |
| 234 | static int filter_pred_strloc(struct filter_pred *pred, void *event, | 221 | static int filter_pred_strloc(struct filter_pred *pred, void *event) |
| 235 | int val1, int val2) | ||
| 236 | { | 222 | { |
| 237 | u32 str_item = *(u32 *)(event + pred->offset); | 223 | u32 str_item = *(u32 *)(event + pred->offset); |
| 238 | int str_loc = str_item & 0xffff; | 224 | int str_loc = str_item & 0xffff; |
| @@ -247,8 +233,7 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event, | |||
| 247 | return match; | 233 | return match; |
| 248 | } | 234 | } |
| 249 | 235 | ||
| 250 | static int filter_pred_none(struct filter_pred *pred, void *event, | 236 | static int filter_pred_none(struct filter_pred *pred, void *event) |
| 251 | int val1, int val2) | ||
| 252 | { | 237 | { |
| 253 | return 0; | 238 | return 0; |
| 254 | } | 239 | } |
| @@ -377,32 +362,147 @@ static void filter_build_regex(struct filter_pred *pred) | |||
| 377 | pred->not ^= not; | 362 | pred->not ^= not; |
| 378 | } | 363 | } |
| 379 | 364 | ||
| 365 | enum move_type { | ||
| 366 | MOVE_DOWN, | ||
| 367 | MOVE_UP_FROM_LEFT, | ||
| 368 | MOVE_UP_FROM_RIGHT | ||
| 369 | }; | ||
| 370 | |||
| 371 | static struct filter_pred * | ||
| 372 | get_pred_parent(struct filter_pred *pred, struct filter_pred *preds, | ||
| 373 | int index, enum move_type *move) | ||
| 374 | { | ||
| 375 | if (pred->parent & FILTER_PRED_IS_RIGHT) | ||
| 376 | *move = MOVE_UP_FROM_RIGHT; | ||
| 377 | else | ||
| 378 | *move = MOVE_UP_FROM_LEFT; | ||
| 379 | pred = &preds[pred->parent & ~FILTER_PRED_IS_RIGHT]; | ||
| 380 | |||
| 381 | return pred; | ||
| 382 | } | ||
| 383 | |||
| 384 | /* | ||
| 385 | * A series of AND or ORs where found together. Instead of | ||
| 386 | * climbing up and down the tree branches, an array of the | ||
| 387 | * ops were made in order of checks. We can just move across | ||
| 388 | * the array and short circuit if needed. | ||
| 389 | */ | ||
| 390 | static int process_ops(struct filter_pred *preds, | ||
| 391 | struct filter_pred *op, void *rec) | ||
| 392 | { | ||
| 393 | struct filter_pred *pred; | ||
| 394 | int type; | ||
| 395 | int match; | ||
| 396 | int i; | ||
| 397 | |||
| 398 | /* | ||
| 399 | * Micro-optimization: We set type to true if op | ||
| 400 | * is an OR and false otherwise (AND). Then we | ||
| 401 | * just need to test if the match is equal to | ||
| 402 | * the type, and if it is, we can short circuit the | ||
| 403 | * rest of the checks: | ||
| 404 | * | ||
| 405 | * if ((match && op->op == OP_OR) || | ||
| 406 | * (!match && op->op == OP_AND)) | ||
| 407 | * return match; | ||
| 408 | */ | ||
| 409 | type = op->op == OP_OR; | ||
| 410 | |||
| 411 | for (i = 0; i < op->val; i++) { | ||
| 412 | pred = &preds[op->ops[i]]; | ||
| 413 | match = pred->fn(pred, rec); | ||
| 414 | if (!!match == type) | ||
| 415 | return match; | ||
| 416 | } | ||
| 417 | return match; | ||
| 418 | } | ||
| 419 | |||
| 380 | /* return 1 if event matches, 0 otherwise (discard) */ | 420 | /* return 1 if event matches, 0 otherwise (discard) */ |
| 381 | int filter_match_preds(struct event_filter *filter, void *rec) | 421 | int filter_match_preds(struct event_filter *filter, void *rec) |
| 382 | { | 422 | { |
| 383 | int match, top = 0, val1 = 0, val2 = 0; | 423 | int match = -1; |
| 384 | int stack[MAX_FILTER_PRED]; | 424 | enum move_type move = MOVE_DOWN; |
| 425 | struct filter_pred *preds; | ||
| 385 | struct filter_pred *pred; | 426 | struct filter_pred *pred; |
| 386 | int i; | 427 | struct filter_pred *root; |
| 428 | int n_preds; | ||
| 429 | int done = 0; | ||
| 430 | |||
| 431 | /* no filter is considered a match */ | ||
| 432 | if (!filter) | ||
| 433 | return 1; | ||
| 434 | |||
| 435 | n_preds = filter->n_preds; | ||
| 436 | |||
| 437 | if (!n_preds) | ||
| 438 | return 1; | ||
| 439 | |||
| 440 | /* | ||
| 441 | * n_preds, root and filter->preds are protect with preemption disabled. | ||
| 442 | */ | ||
| 443 | preds = rcu_dereference_sched(filter->preds); | ||
| 444 | root = rcu_dereference_sched(filter->root); | ||
| 445 | if (!root) | ||
| 446 | return 1; | ||
| 447 | |||
| 448 | pred = root; | ||
| 387 | 449 | ||
| 388 | for (i = 0; i < filter->n_preds; i++) { | 450 | /* match is currently meaningless */ |
| 389 | pred = filter->preds[i]; | 451 | match = -1; |
| 390 | if (!pred->pop_n) { | 452 | |
| 391 | match = pred->fn(pred, rec, val1, val2); | 453 | do { |
| 392 | stack[top++] = match; | 454 | switch (move) { |
| 455 | case MOVE_DOWN: | ||
| 456 | /* only AND and OR have children */ | ||
| 457 | if (pred->left != FILTER_PRED_INVALID) { | ||
| 458 | /* If ops is set, then it was folded. */ | ||
| 459 | if (!pred->ops) { | ||
| 460 | /* keep going to down the left side */ | ||
| 461 | pred = &preds[pred->left]; | ||
| 462 | continue; | ||
| 463 | } | ||
| 464 | /* We can treat folded ops as a leaf node */ | ||
| 465 | match = process_ops(preds, pred, rec); | ||
| 466 | } else | ||
| 467 | match = pred->fn(pred, rec); | ||
| 468 | /* If this pred is the only pred */ | ||
| 469 | if (pred == root) | ||
| 470 | break; | ||
| 471 | pred = get_pred_parent(pred, preds, | ||
| 472 | pred->parent, &move); | ||
| 473 | continue; | ||
| 474 | case MOVE_UP_FROM_LEFT: | ||
| 475 | /* | ||
| 476 | * Check for short circuits. | ||
| 477 | * | ||
| 478 | * Optimization: !!match == (pred->op == OP_OR) | ||
| 479 | * is the same as: | ||
| 480 | * if ((match && pred->op == OP_OR) || | ||
| 481 | * (!match && pred->op == OP_AND)) | ||
| 482 | */ | ||
| 483 | if (!!match == (pred->op == OP_OR)) { | ||
| 484 | if (pred == root) | ||
| 485 | break; | ||
| 486 | pred = get_pred_parent(pred, preds, | ||
| 487 | pred->parent, &move); | ||
| 488 | continue; | ||
| 489 | } | ||
| 490 | /* now go down the right side of the tree. */ | ||
| 491 | pred = &preds[pred->right]; | ||
| 492 | move = MOVE_DOWN; | ||
| 493 | continue; | ||
| 494 | case MOVE_UP_FROM_RIGHT: | ||
| 495 | /* We finished this equation. */ | ||
| 496 | if (pred == root) | ||
| 497 | break; | ||
| 498 | pred = get_pred_parent(pred, preds, | ||
| 499 | pred->parent, &move); | ||
| 393 | continue; | 500 | continue; |
| 394 | } | 501 | } |
| 395 | if (pred->pop_n > top) { | 502 | done = 1; |
| 396 | WARN_ON_ONCE(1); | 503 | } while (!done); |
| 397 | return 0; | ||
| 398 | } | ||
| 399 | val1 = stack[--top]; | ||
| 400 | val2 = stack[--top]; | ||
| 401 | match = pred->fn(pred, rec, val1, val2); | ||
| 402 | stack[top++] = match; | ||
| 403 | } | ||
| 404 | 504 | ||
| 405 | return stack[--top]; | 505 | return match; |
| 406 | } | 506 | } |
| 407 | EXPORT_SYMBOL_GPL(filter_match_preds); | 507 | EXPORT_SYMBOL_GPL(filter_match_preds); |
| 408 | 508 | ||
| @@ -414,6 +514,9 @@ static void parse_error(struct filter_parse_state *ps, int err, int pos) | |||
| 414 | 514 | ||
| 415 | static void remove_filter_string(struct event_filter *filter) | 515 | static void remove_filter_string(struct event_filter *filter) |
| 416 | { | 516 | { |
| 517 | if (!filter) | ||
| 518 | return; | ||
| 519 | |||
| 417 | kfree(filter->filter_string); | 520 | kfree(filter->filter_string); |
| 418 | filter->filter_string = NULL; | 521 | filter->filter_string = NULL; |
| 419 | } | 522 | } |
| @@ -473,9 +576,10 @@ static void append_filter_err(struct filter_parse_state *ps, | |||
| 473 | 576 | ||
| 474 | void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) | 577 | void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) |
| 475 | { | 578 | { |
| 476 | struct event_filter *filter = call->filter; | 579 | struct event_filter *filter; |
| 477 | 580 | ||
| 478 | mutex_lock(&event_mutex); | 581 | mutex_lock(&event_mutex); |
| 582 | filter = call->filter; | ||
| 479 | if (filter && filter->filter_string) | 583 | if (filter && filter->filter_string) |
| 480 | trace_seq_printf(s, "%s\n", filter->filter_string); | 584 | trace_seq_printf(s, "%s\n", filter->filter_string); |
| 481 | else | 585 | else |
| @@ -486,9 +590,10 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) | |||
| 486 | void print_subsystem_event_filter(struct event_subsystem *system, | 590 | void print_subsystem_event_filter(struct event_subsystem *system, |
| 487 | struct trace_seq *s) | 591 | struct trace_seq *s) |
| 488 | { | 592 | { |
| 489 | struct event_filter *filter = system->filter; | 593 | struct event_filter *filter; |
| 490 | 594 | ||
| 491 | mutex_lock(&event_mutex); | 595 | mutex_lock(&event_mutex); |
| 596 | filter = system->filter; | ||
| 492 | if (filter && filter->filter_string) | 597 | if (filter && filter->filter_string) |
| 493 | trace_seq_printf(s, "%s\n", filter->filter_string); | 598 | trace_seq_printf(s, "%s\n", filter->filter_string); |
| 494 | else | 599 | else |
| @@ -539,10 +644,58 @@ static void filter_clear_pred(struct filter_pred *pred) | |||
| 539 | pred->regex.len = 0; | 644 | pred->regex.len = 0; |
| 540 | } | 645 | } |
| 541 | 646 | ||
| 542 | static int filter_set_pred(struct filter_pred *dest, | 647 | static int __alloc_pred_stack(struct pred_stack *stack, int n_preds) |
| 648 | { | ||
| 649 | stack->preds = kzalloc(sizeof(*stack->preds)*(n_preds + 1), GFP_KERNEL); | ||
| 650 | if (!stack->preds) | ||
| 651 | return -ENOMEM; | ||
| 652 | stack->index = n_preds; | ||
| 653 | return 0; | ||
| 654 | } | ||
| 655 | |||
| 656 | static void __free_pred_stack(struct pred_stack *stack) | ||
| 657 | { | ||
| 658 | kfree(stack->preds); | ||
| 659 | stack->index = 0; | ||
| 660 | } | ||
| 661 | |||
| 662 | static int __push_pred_stack(struct pred_stack *stack, | ||
| 663 | struct filter_pred *pred) | ||
| 664 | { | ||
| 665 | int index = stack->index; | ||
| 666 | |||
| 667 | if (WARN_ON(index == 0)) | ||
| 668 | return -ENOSPC; | ||
| 669 | |||
| 670 | stack->preds[--index] = pred; | ||
| 671 | stack->index = index; | ||
| 672 | return 0; | ||
| 673 | } | ||
| 674 | |||
| 675 | static struct filter_pred * | ||
| 676 | __pop_pred_stack(struct pred_stack *stack) | ||
| 677 | { | ||
| 678 | struct filter_pred *pred; | ||
| 679 | int index = stack->index; | ||
| 680 | |||
| 681 | pred = stack->preds[index++]; | ||
| 682 | if (!pred) | ||
| 683 | return NULL; | ||
| 684 | |||
| 685 | stack->index = index; | ||
| 686 | return pred; | ||
| 687 | } | ||
| 688 | |||
| 689 | static int filter_set_pred(struct event_filter *filter, | ||
| 690 | int idx, | ||
| 691 | struct pred_stack *stack, | ||
| 543 | struct filter_pred *src, | 692 | struct filter_pred *src, |
| 544 | filter_pred_fn_t fn) | 693 | filter_pred_fn_t fn) |
| 545 | { | 694 | { |
| 695 | struct filter_pred *dest = &filter->preds[idx]; | ||
| 696 | struct filter_pred *left; | ||
| 697 | struct filter_pred *right; | ||
| 698 | |||
| 546 | *dest = *src; | 699 | *dest = *src; |
| 547 | if (src->field_name) { | 700 | if (src->field_name) { |
| 548 | dest->field_name = kstrdup(src->field_name, GFP_KERNEL); | 701 | dest->field_name = kstrdup(src->field_name, GFP_KERNEL); |
| @@ -550,116 +703,140 @@ static int filter_set_pred(struct filter_pred *dest, | |||
| 550 | return -ENOMEM; | 703 | return -ENOMEM; |
| 551 | } | 704 | } |
| 552 | dest->fn = fn; | 705 | dest->fn = fn; |
| 706 | dest->index = idx; | ||
| 553 | 707 | ||
| 554 | return 0; | 708 | if (dest->op == OP_OR || dest->op == OP_AND) { |
| 709 | right = __pop_pred_stack(stack); | ||
| 710 | left = __pop_pred_stack(stack); | ||
| 711 | if (!left || !right) | ||
| 712 | return -EINVAL; | ||
| 713 | /* | ||
| 714 | * If both children can be folded | ||
| 715 | * and they are the same op as this op or a leaf, | ||
| 716 | * then this op can be folded. | ||
| 717 | */ | ||
| 718 | if (left->index & FILTER_PRED_FOLD && | ||
| 719 | (left->op == dest->op || | ||
| 720 | left->left == FILTER_PRED_INVALID) && | ||
| 721 | right->index & FILTER_PRED_FOLD && | ||
| 722 | (right->op == dest->op || | ||
| 723 | right->left == FILTER_PRED_INVALID)) | ||
| 724 | dest->index |= FILTER_PRED_FOLD; | ||
| 725 | |||
| 726 | dest->left = left->index & ~FILTER_PRED_FOLD; | ||
| 727 | dest->right = right->index & ~FILTER_PRED_FOLD; | ||
| 728 | left->parent = dest->index & ~FILTER_PRED_FOLD; | ||
| 729 | right->parent = dest->index | FILTER_PRED_IS_RIGHT; | ||
| 730 | } else { | ||
| 731 | /* | ||
| 732 | * Make dest->left invalid to be used as a quick | ||
| 733 | * way to know this is a leaf node. | ||
| 734 | */ | ||
| 735 | dest->left = FILTER_PRED_INVALID; | ||
| 736 | |||
| 737 | /* All leafs allow folding the parent ops. */ | ||
| 738 | dest->index |= FILTER_PRED_FOLD; | ||
| 739 | } | ||
| 740 | |||
| 741 | return __push_pred_stack(stack, dest); | ||
| 555 | } | 742 | } |
| 556 | 743 | ||
| 557 | static void filter_disable_preds(struct ftrace_event_call *call) | 744 | static void __free_preds(struct event_filter *filter) |
| 558 | { | 745 | { |
| 559 | struct event_filter *filter = call->filter; | ||
| 560 | int i; | 746 | int i; |
| 561 | 747 | ||
| 562 | call->flags &= ~TRACE_EVENT_FL_FILTERED; | 748 | if (filter->preds) { |
| 749 | for (i = 0; i < filter->a_preds; i++) | ||
| 750 | kfree(filter->preds[i].field_name); | ||
| 751 | kfree(filter->preds); | ||
| 752 | filter->preds = NULL; | ||
| 753 | } | ||
| 754 | filter->a_preds = 0; | ||
| 563 | filter->n_preds = 0; | 755 | filter->n_preds = 0; |
| 564 | |||
| 565 | for (i = 0; i < MAX_FILTER_PRED; i++) | ||
| 566 | filter->preds[i]->fn = filter_pred_none; | ||
| 567 | } | 756 | } |
| 568 | 757 | ||
| 569 | static void __free_preds(struct event_filter *filter) | 758 | static void filter_disable(struct ftrace_event_call *call) |
| 570 | { | 759 | { |
| 571 | int i; | 760 | call->flags &= ~TRACE_EVENT_FL_FILTERED; |
| 761 | } | ||
| 572 | 762 | ||
| 763 | static void __free_filter(struct event_filter *filter) | ||
| 764 | { | ||
| 573 | if (!filter) | 765 | if (!filter) |
| 574 | return; | 766 | return; |
| 575 | 767 | ||
| 576 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 768 | __free_preds(filter); |
| 577 | if (filter->preds[i]) | ||
| 578 | filter_free_pred(filter->preds[i]); | ||
| 579 | } | ||
| 580 | kfree(filter->preds); | ||
| 581 | kfree(filter->filter_string); | 769 | kfree(filter->filter_string); |
| 582 | kfree(filter); | 770 | kfree(filter); |
| 583 | } | 771 | } |
| 584 | 772 | ||
| 773 | /* | ||
| 774 | * Called when destroying the ftrace_event_call. | ||
| 775 | * The call is being freed, so we do not need to worry about | ||
| 776 | * the call being currently used. This is for module code removing | ||
| 777 | * the tracepoints from within it. | ||
| 778 | */ | ||
| 585 | void destroy_preds(struct ftrace_event_call *call) | 779 | void destroy_preds(struct ftrace_event_call *call) |
| 586 | { | 780 | { |
| 587 | __free_preds(call->filter); | 781 | __free_filter(call->filter); |
| 588 | call->filter = NULL; | 782 | call->filter = NULL; |
| 589 | call->flags &= ~TRACE_EVENT_FL_FILTERED; | ||
| 590 | } | 783 | } |
| 591 | 784 | ||
| 592 | static struct event_filter *__alloc_preds(void) | 785 | static struct event_filter *__alloc_filter(void) |
| 593 | { | 786 | { |
| 594 | struct event_filter *filter; | 787 | struct event_filter *filter; |
| 788 | |||
| 789 | filter = kzalloc(sizeof(*filter), GFP_KERNEL); | ||
| 790 | return filter; | ||
| 791 | } | ||
| 792 | |||
| 793 | static int __alloc_preds(struct event_filter *filter, int n_preds) | ||
| 794 | { | ||
| 595 | struct filter_pred *pred; | 795 | struct filter_pred *pred; |
| 596 | int i; | 796 | int i; |
| 597 | 797 | ||
| 598 | filter = kzalloc(sizeof(*filter), GFP_KERNEL); | 798 | if (filter->preds) |
| 599 | if (!filter) | 799 | __free_preds(filter); |
| 600 | return ERR_PTR(-ENOMEM); | ||
| 601 | 800 | ||
| 602 | filter->n_preds = 0; | 801 | filter->preds = |
| 802 | kzalloc(sizeof(*filter->preds) * n_preds, GFP_KERNEL); | ||
| 603 | 803 | ||
| 604 | filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL); | ||
| 605 | if (!filter->preds) | 804 | if (!filter->preds) |
| 606 | goto oom; | 805 | return -ENOMEM; |
| 607 | 806 | ||
| 608 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 807 | filter->a_preds = n_preds; |
| 609 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); | 808 | filter->n_preds = 0; |
| 610 | if (!pred) | 809 | |
| 611 | goto oom; | 810 | for (i = 0; i < n_preds; i++) { |
| 811 | pred = &filter->preds[i]; | ||
| 612 | pred->fn = filter_pred_none; | 812 | pred->fn = filter_pred_none; |
| 613 | filter->preds[i] = pred; | ||
| 614 | } | 813 | } |
| 615 | 814 | ||
| 616 | return filter; | ||
| 617 | |||
| 618 | oom: | ||
| 619 | __free_preds(filter); | ||
| 620 | return ERR_PTR(-ENOMEM); | ||
| 621 | } | ||
| 622 | |||
| 623 | static int init_preds(struct ftrace_event_call *call) | ||
| 624 | { | ||
| 625 | if (call->filter) | ||
| 626 | return 0; | ||
| 627 | |||
| 628 | call->flags &= ~TRACE_EVENT_FL_FILTERED; | ||
| 629 | call->filter = __alloc_preds(); | ||
| 630 | if (IS_ERR(call->filter)) | ||
| 631 | return PTR_ERR(call->filter); | ||
| 632 | |||
| 633 | return 0; | 815 | return 0; |
| 634 | } | 816 | } |
| 635 | 817 | ||
| 636 | static int init_subsystem_preds(struct event_subsystem *system) | 818 | static void filter_free_subsystem_preds(struct event_subsystem *system) |
| 637 | { | 819 | { |
| 638 | struct ftrace_event_call *call; | 820 | struct ftrace_event_call *call; |
| 639 | int err; | ||
| 640 | 821 | ||
| 641 | list_for_each_entry(call, &ftrace_events, list) { | 822 | list_for_each_entry(call, &ftrace_events, list) { |
| 642 | if (strcmp(call->class->system, system->name) != 0) | 823 | if (strcmp(call->class->system, system->name) != 0) |
| 643 | continue; | 824 | continue; |
| 644 | 825 | ||
| 645 | err = init_preds(call); | 826 | filter_disable(call); |
| 646 | if (err) | 827 | remove_filter_string(call->filter); |
| 647 | return err; | ||
| 648 | } | 828 | } |
| 649 | |||
| 650 | return 0; | ||
| 651 | } | 829 | } |
| 652 | 830 | ||
| 653 | static void filter_free_subsystem_preds(struct event_subsystem *system) | 831 | static void filter_free_subsystem_filters(struct event_subsystem *system) |
| 654 | { | 832 | { |
| 655 | struct ftrace_event_call *call; | 833 | struct ftrace_event_call *call; |
| 656 | 834 | ||
| 657 | list_for_each_entry(call, &ftrace_events, list) { | 835 | list_for_each_entry(call, &ftrace_events, list) { |
| 658 | if (strcmp(call->class->system, system->name) != 0) | 836 | if (strcmp(call->class->system, system->name) != 0) |
| 659 | continue; | 837 | continue; |
| 660 | 838 | __free_filter(call->filter); | |
| 661 | filter_disable_preds(call); | 839 | call->filter = NULL; |
| 662 | remove_filter_string(call->filter); | ||
| 663 | } | 840 | } |
| 664 | } | 841 | } |
| 665 | 842 | ||
| @@ -667,18 +844,19 @@ static int filter_add_pred_fn(struct filter_parse_state *ps, | |||
| 667 | struct ftrace_event_call *call, | 844 | struct ftrace_event_call *call, |
| 668 | struct event_filter *filter, | 845 | struct event_filter *filter, |
| 669 | struct filter_pred *pred, | 846 | struct filter_pred *pred, |
| 847 | struct pred_stack *stack, | ||
| 670 | filter_pred_fn_t fn) | 848 | filter_pred_fn_t fn) |
| 671 | { | 849 | { |
| 672 | int idx, err; | 850 | int idx, err; |
| 673 | 851 | ||
| 674 | if (filter->n_preds == MAX_FILTER_PRED) { | 852 | if (WARN_ON(filter->n_preds == filter->a_preds)) { |
| 675 | parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); | 853 | parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); |
| 676 | return -ENOSPC; | 854 | return -ENOSPC; |
| 677 | } | 855 | } |
| 678 | 856 | ||
| 679 | idx = filter->n_preds; | 857 | idx = filter->n_preds; |
| 680 | filter_clear_pred(filter->preds[idx]); | 858 | filter_clear_pred(&filter->preds[idx]); |
| 681 | err = filter_set_pred(filter->preds[idx], pred, fn); | 859 | err = filter_set_pred(filter, idx, stack, pred, fn); |
| 682 | if (err) | 860 | if (err) |
| 683 | return err; | 861 | return err; |
| 684 | 862 | ||
| @@ -763,6 +941,7 @@ static int filter_add_pred(struct filter_parse_state *ps, | |||
| 763 | struct ftrace_event_call *call, | 941 | struct ftrace_event_call *call, |
| 764 | struct event_filter *filter, | 942 | struct event_filter *filter, |
| 765 | struct filter_pred *pred, | 943 | struct filter_pred *pred, |
| 944 | struct pred_stack *stack, | ||
| 766 | bool dry_run) | 945 | bool dry_run) |
| 767 | { | 946 | { |
| 768 | struct ftrace_event_field *field; | 947 | struct ftrace_event_field *field; |
| @@ -770,17 +949,12 @@ static int filter_add_pred(struct filter_parse_state *ps, | |||
| 770 | unsigned long long val; | 949 | unsigned long long val; |
| 771 | int ret; | 950 | int ret; |
| 772 | 951 | ||
| 773 | pred->fn = filter_pred_none; | 952 | fn = pred->fn = filter_pred_none; |
| 774 | 953 | ||
| 775 | if (pred->op == OP_AND) { | 954 | if (pred->op == OP_AND) |
| 776 | pred->pop_n = 2; | ||
| 777 | fn = filter_pred_and; | ||
| 778 | goto add_pred_fn; | 955 | goto add_pred_fn; |
| 779 | } else if (pred->op == OP_OR) { | 956 | else if (pred->op == OP_OR) |
| 780 | pred->pop_n = 2; | ||
| 781 | fn = filter_pred_or; | ||
| 782 | goto add_pred_fn; | 957 | goto add_pred_fn; |
| 783 | } | ||
| 784 | 958 | ||
| 785 | field = find_event_field(call, pred->field_name); | 959 | field = find_event_field(call, pred->field_name); |
| 786 | if (!field) { | 960 | if (!field) { |
| @@ -829,7 +1003,7 @@ static int filter_add_pred(struct filter_parse_state *ps, | |||
| 829 | 1003 | ||
| 830 | add_pred_fn: | 1004 | add_pred_fn: |
| 831 | if (!dry_run) | 1005 | if (!dry_run) |
| 832 | return filter_add_pred_fn(ps, call, filter, pred, fn); | 1006 | return filter_add_pred_fn(ps, call, filter, pred, stack, fn); |
| 833 | return 0; | 1007 | return 0; |
| 834 | } | 1008 | } |
| 835 | 1009 | ||
| @@ -1187,6 +1361,234 @@ static int check_preds(struct filter_parse_state *ps) | |||
| 1187 | return 0; | 1361 | return 0; |
| 1188 | } | 1362 | } |
| 1189 | 1363 | ||
| 1364 | static int count_preds(struct filter_parse_state *ps) | ||
| 1365 | { | ||
| 1366 | struct postfix_elt *elt; | ||
| 1367 | int n_preds = 0; | ||
| 1368 | |||
| 1369 | list_for_each_entry(elt, &ps->postfix, list) { | ||
| 1370 | if (elt->op == OP_NONE) | ||
| 1371 | continue; | ||
| 1372 | n_preds++; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | return n_preds; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* | ||
| 1379 | * The tree is walked at filtering of an event. If the tree is not correctly | ||
| 1380 | * built, it may cause an infinite loop. Check here that the tree does | ||
| 1381 | * indeed terminate. | ||
| 1382 | */ | ||
| 1383 | static int check_pred_tree(struct event_filter *filter, | ||
| 1384 | struct filter_pred *root) | ||
| 1385 | { | ||
| 1386 | struct filter_pred *preds; | ||
| 1387 | struct filter_pred *pred; | ||
| 1388 | enum move_type move = MOVE_DOWN; | ||
| 1389 | int count = 0; | ||
| 1390 | int done = 0; | ||
| 1391 | int max; | ||
| 1392 | |||
| 1393 | /* | ||
| 1394 | * The max that we can hit a node is three times. | ||
| 1395 | * Once going down, once coming up from left, and | ||
| 1396 | * once coming up from right. This is more than enough | ||
| 1397 | * since leafs are only hit a single time. | ||
| 1398 | */ | ||
| 1399 | max = 3 * filter->n_preds; | ||
| 1400 | |||
| 1401 | preds = filter->preds; | ||
| 1402 | if (!preds) | ||
| 1403 | return -EINVAL; | ||
| 1404 | pred = root; | ||
| 1405 | |||
| 1406 | do { | ||
| 1407 | if (WARN_ON(count++ > max)) | ||
| 1408 | return -EINVAL; | ||
| 1409 | |||
| 1410 | switch (move) { | ||
| 1411 | case MOVE_DOWN: | ||
| 1412 | if (pred->left != FILTER_PRED_INVALID) { | ||
| 1413 | pred = &preds[pred->left]; | ||
| 1414 | continue; | ||
| 1415 | } | ||
| 1416 | /* A leaf at the root is just a leaf in the tree */ | ||
| 1417 | if (pred == root) | ||
| 1418 | break; | ||
| 1419 | pred = get_pred_parent(pred, preds, | ||
| 1420 | pred->parent, &move); | ||
| 1421 | continue; | ||
| 1422 | case MOVE_UP_FROM_LEFT: | ||
| 1423 | pred = &preds[pred->right]; | ||
| 1424 | move = MOVE_DOWN; | ||
| 1425 | continue; | ||
| 1426 | case MOVE_UP_FROM_RIGHT: | ||
| 1427 | if (pred == root) | ||
| 1428 | break; | ||
| 1429 | pred = get_pred_parent(pred, preds, | ||
| 1430 | pred->parent, &move); | ||
| 1431 | continue; | ||
| 1432 | } | ||
| 1433 | done = 1; | ||
| 1434 | } while (!done); | ||
| 1435 | |||
| 1436 | /* We are fine. */ | ||
| 1437 | return 0; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static int count_leafs(struct filter_pred *preds, struct filter_pred *root) | ||
| 1441 | { | ||
| 1442 | struct filter_pred *pred; | ||
| 1443 | enum move_type move = MOVE_DOWN; | ||
| 1444 | int count = 0; | ||
| 1445 | int done = 0; | ||
| 1446 | |||
| 1447 | pred = root; | ||
| 1448 | |||
| 1449 | do { | ||
| 1450 | switch (move) { | ||
| 1451 | case MOVE_DOWN: | ||
| 1452 | if (pred->left != FILTER_PRED_INVALID) { | ||
| 1453 | pred = &preds[pred->left]; | ||
| 1454 | continue; | ||
| 1455 | } | ||
| 1456 | /* A leaf at the root is just a leaf in the tree */ | ||
| 1457 | if (pred == root) | ||
| 1458 | return 1; | ||
| 1459 | count++; | ||
| 1460 | pred = get_pred_parent(pred, preds, | ||
| 1461 | pred->parent, &move); | ||
| 1462 | continue; | ||
| 1463 | case MOVE_UP_FROM_LEFT: | ||
| 1464 | pred = &preds[pred->right]; | ||
| 1465 | move = MOVE_DOWN; | ||
| 1466 | continue; | ||
| 1467 | case MOVE_UP_FROM_RIGHT: | ||
| 1468 | if (pred == root) | ||
| 1469 | break; | ||
| 1470 | pred = get_pred_parent(pred, preds, | ||
| 1471 | pred->parent, &move); | ||
| 1472 | continue; | ||
| 1473 | } | ||
| 1474 | done = 1; | ||
| 1475 | } while (!done); | ||
| 1476 | |||
| 1477 | return count; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | static int fold_pred(struct filter_pred *preds, struct filter_pred *root) | ||
| 1481 | { | ||
| 1482 | struct filter_pred *pred; | ||
| 1483 | enum move_type move = MOVE_DOWN; | ||
| 1484 | int count = 0; | ||
| 1485 | int children; | ||
| 1486 | int done = 0; | ||
| 1487 | |||
| 1488 | /* No need to keep the fold flag */ | ||
| 1489 | root->index &= ~FILTER_PRED_FOLD; | ||
| 1490 | |||
| 1491 | /* If the root is a leaf then do nothing */ | ||
| 1492 | if (root->left == FILTER_PRED_INVALID) | ||
| 1493 | return 0; | ||
| 1494 | |||
| 1495 | /* count the children */ | ||
| 1496 | children = count_leafs(preds, &preds[root->left]); | ||
| 1497 | children += count_leafs(preds, &preds[root->right]); | ||
| 1498 | |||
| 1499 | root->ops = kzalloc(sizeof(*root->ops) * children, GFP_KERNEL); | ||
| 1500 | if (!root->ops) | ||
| 1501 | return -ENOMEM; | ||
| 1502 | |||
| 1503 | root->val = children; | ||
| 1504 | |||
| 1505 | pred = root; | ||
| 1506 | do { | ||
| 1507 | switch (move) { | ||
| 1508 | case MOVE_DOWN: | ||
| 1509 | if (pred->left != FILTER_PRED_INVALID) { | ||
| 1510 | pred = &preds[pred->left]; | ||
| 1511 | continue; | ||
| 1512 | } | ||
| 1513 | if (WARN_ON(count == children)) | ||
| 1514 | return -EINVAL; | ||
| 1515 | pred->index &= ~FILTER_PRED_FOLD; | ||
| 1516 | root->ops[count++] = pred->index; | ||
| 1517 | pred = get_pred_parent(pred, preds, | ||
| 1518 | pred->parent, &move); | ||
| 1519 | continue; | ||
| 1520 | case MOVE_UP_FROM_LEFT: | ||
| 1521 | pred = &preds[pred->right]; | ||
| 1522 | move = MOVE_DOWN; | ||
| 1523 | continue; | ||
| 1524 | case MOVE_UP_FROM_RIGHT: | ||
| 1525 | if (pred == root) | ||
| 1526 | break; | ||
| 1527 | pred = get_pred_parent(pred, preds, | ||
| 1528 | pred->parent, &move); | ||
| 1529 | continue; | ||
| 1530 | } | ||
| 1531 | done = 1; | ||
| 1532 | } while (!done); | ||
| 1533 | |||
| 1534 | return 0; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | /* | ||
| 1538 | * To optimize the processing of the ops, if we have several "ors" or | ||
| 1539 | * "ands" together, we can put them in an array and process them all | ||
| 1540 | * together speeding up the filter logic. | ||
| 1541 | */ | ||
| 1542 | static int fold_pred_tree(struct event_filter *filter, | ||
| 1543 | struct filter_pred *root) | ||
| 1544 | { | ||
| 1545 | struct filter_pred *preds; | ||
| 1546 | struct filter_pred *pred; | ||
| 1547 | enum move_type move = MOVE_DOWN; | ||
| 1548 | int done = 0; | ||
| 1549 | int err; | ||
| 1550 | |||
| 1551 | preds = filter->preds; | ||
| 1552 | if (!preds) | ||
| 1553 | return -EINVAL; | ||
| 1554 | pred = root; | ||
| 1555 | |||
| 1556 | do { | ||
| 1557 | switch (move) { | ||
| 1558 | case MOVE_DOWN: | ||
| 1559 | if (pred->index & FILTER_PRED_FOLD) { | ||
| 1560 | err = fold_pred(preds, pred); | ||
| 1561 | if (err) | ||
| 1562 | return err; | ||
| 1563 | /* Folded nodes are like leafs */ | ||
| 1564 | } else if (pred->left != FILTER_PRED_INVALID) { | ||
| 1565 | pred = &preds[pred->left]; | ||
| 1566 | continue; | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | /* A leaf at the root is just a leaf in the tree */ | ||
| 1570 | if (pred == root) | ||
| 1571 | break; | ||
| 1572 | pred = get_pred_parent(pred, preds, | ||
| 1573 | pred->parent, &move); | ||
| 1574 | continue; | ||
| 1575 | case MOVE_UP_FROM_LEFT: | ||
| 1576 | pred = &preds[pred->right]; | ||
| 1577 | move = MOVE_DOWN; | ||
| 1578 | continue; | ||
| 1579 | case MOVE_UP_FROM_RIGHT: | ||
| 1580 | if (pred == root) | ||
| 1581 | break; | ||
| 1582 | pred = get_pred_parent(pred, preds, | ||
| 1583 | pred->parent, &move); | ||
| 1584 | continue; | ||
| 1585 | } | ||
| 1586 | done = 1; | ||
| 1587 | } while (!done); | ||
| 1588 | |||
| 1589 | return 0; | ||
| 1590 | } | ||
| 1591 | |||
| 1190 | static int replace_preds(struct ftrace_event_call *call, | 1592 | static int replace_preds(struct ftrace_event_call *call, |
| 1191 | struct event_filter *filter, | 1593 | struct event_filter *filter, |
| 1192 | struct filter_parse_state *ps, | 1594 | struct filter_parse_state *ps, |
| @@ -1195,14 +1597,32 @@ static int replace_preds(struct ftrace_event_call *call, | |||
| 1195 | { | 1597 | { |
| 1196 | char *operand1 = NULL, *operand2 = NULL; | 1598 | char *operand1 = NULL, *operand2 = NULL; |
| 1197 | struct filter_pred *pred; | 1599 | struct filter_pred *pred; |
| 1600 | struct filter_pred *root; | ||
| 1198 | struct postfix_elt *elt; | 1601 | struct postfix_elt *elt; |
| 1602 | struct pred_stack stack = { }; /* init to NULL */ | ||
| 1199 | int err; | 1603 | int err; |
| 1200 | int n_preds = 0; | 1604 | int n_preds = 0; |
| 1201 | 1605 | ||
| 1606 | n_preds = count_preds(ps); | ||
| 1607 | if (n_preds >= MAX_FILTER_PRED) { | ||
| 1608 | parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); | ||
| 1609 | return -ENOSPC; | ||
| 1610 | } | ||
| 1611 | |||
| 1202 | err = check_preds(ps); | 1612 | err = check_preds(ps); |
| 1203 | if (err) | 1613 | if (err) |
| 1204 | return err; | 1614 | return err; |
| 1205 | 1615 | ||
| 1616 | if (!dry_run) { | ||
| 1617 | err = __alloc_pred_stack(&stack, n_preds); | ||
| 1618 | if (err) | ||
| 1619 | return err; | ||
| 1620 | err = __alloc_preds(filter, n_preds); | ||
| 1621 | if (err) | ||
| 1622 | goto fail; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | n_preds = 0; | ||
| 1206 | list_for_each_entry(elt, &ps->postfix, list) { | 1626 | list_for_each_entry(elt, &ps->postfix, list) { |
| 1207 | if (elt->op == OP_NONE) { | 1627 | if (elt->op == OP_NONE) { |
| 1208 | if (!operand1) | 1628 | if (!operand1) |
| @@ -1211,14 +1631,16 @@ static int replace_preds(struct ftrace_event_call *call, | |||
| 1211 | operand2 = elt->operand; | 1631 | operand2 = elt->operand; |
| 1212 | else { | 1632 | else { |
| 1213 | parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0); | 1633 | parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0); |
| 1214 | return -EINVAL; | 1634 | err = -EINVAL; |
| 1635 | goto fail; | ||
| 1215 | } | 1636 | } |
| 1216 | continue; | 1637 | continue; |
| 1217 | } | 1638 | } |
| 1218 | 1639 | ||
| 1219 | if (n_preds++ == MAX_FILTER_PRED) { | 1640 | if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) { |
| 1220 | parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); | 1641 | parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); |
| 1221 | return -ENOSPC; | 1642 | err = -ENOSPC; |
| 1643 | goto fail; | ||
| 1222 | } | 1644 | } |
| 1223 | 1645 | ||
| 1224 | if (elt->op == OP_AND || elt->op == OP_OR) { | 1646 | if (elt->op == OP_AND || elt->op == OP_OR) { |
| @@ -1228,76 +1650,181 @@ static int replace_preds(struct ftrace_event_call *call, | |||
| 1228 | 1650 | ||
| 1229 | if (!operand1 || !operand2) { | 1651 | if (!operand1 || !operand2) { |
| 1230 | parse_error(ps, FILT_ERR_MISSING_FIELD, 0); | 1652 | parse_error(ps, FILT_ERR_MISSING_FIELD, 0); |
| 1231 | return -EINVAL; | 1653 | err = -EINVAL; |
| 1654 | goto fail; | ||
| 1232 | } | 1655 | } |
| 1233 | 1656 | ||
| 1234 | pred = create_pred(elt->op, operand1, operand2); | 1657 | pred = create_pred(elt->op, operand1, operand2); |
| 1235 | add_pred: | 1658 | add_pred: |
| 1236 | if (!pred) | 1659 | if (!pred) { |
| 1237 | return -ENOMEM; | 1660 | err = -ENOMEM; |
| 1238 | err = filter_add_pred(ps, call, filter, pred, dry_run); | 1661 | goto fail; |
| 1662 | } | ||
| 1663 | err = filter_add_pred(ps, call, filter, pred, &stack, dry_run); | ||
| 1239 | filter_free_pred(pred); | 1664 | filter_free_pred(pred); |
| 1240 | if (err) | 1665 | if (err) |
| 1241 | return err; | 1666 | goto fail; |
| 1242 | 1667 | ||
| 1243 | operand1 = operand2 = NULL; | 1668 | operand1 = operand2 = NULL; |
| 1244 | } | 1669 | } |
| 1245 | 1670 | ||
| 1246 | return 0; | 1671 | if (!dry_run) { |
| 1672 | /* We should have one item left on the stack */ | ||
| 1673 | pred = __pop_pred_stack(&stack); | ||
| 1674 | if (!pred) | ||
| 1675 | return -EINVAL; | ||
| 1676 | /* This item is where we start from in matching */ | ||
| 1677 | root = pred; | ||
| 1678 | /* Make sure the stack is empty */ | ||
| 1679 | pred = __pop_pred_stack(&stack); | ||
| 1680 | if (WARN_ON(pred)) { | ||
| 1681 | err = -EINVAL; | ||
| 1682 | filter->root = NULL; | ||
| 1683 | goto fail; | ||
| 1684 | } | ||
| 1685 | err = check_pred_tree(filter, root); | ||
| 1686 | if (err) | ||
| 1687 | goto fail; | ||
| 1688 | |||
| 1689 | /* Optimize the tree */ | ||
| 1690 | err = fold_pred_tree(filter, root); | ||
| 1691 | if (err) | ||
| 1692 | goto fail; | ||
| 1693 | |||
| 1694 | /* We don't set root until we know it works */ | ||
| 1695 | barrier(); | ||
| 1696 | filter->root = root; | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | err = 0; | ||
| 1700 | fail: | ||
| 1701 | __free_pred_stack(&stack); | ||
| 1702 | return err; | ||
| 1247 | } | 1703 | } |
| 1248 | 1704 | ||
| 1705 | struct filter_list { | ||
| 1706 | struct list_head list; | ||
| 1707 | struct event_filter *filter; | ||
| 1708 | }; | ||
| 1709 | |||
| 1249 | static int replace_system_preds(struct event_subsystem *system, | 1710 | static int replace_system_preds(struct event_subsystem *system, |
| 1250 | struct filter_parse_state *ps, | 1711 | struct filter_parse_state *ps, |
| 1251 | char *filter_string) | 1712 | char *filter_string) |
| 1252 | { | 1713 | { |
| 1253 | struct ftrace_event_call *call; | 1714 | struct ftrace_event_call *call; |
| 1715 | struct filter_list *filter_item; | ||
| 1716 | struct filter_list *tmp; | ||
| 1717 | LIST_HEAD(filter_list); | ||
| 1254 | bool fail = true; | 1718 | bool fail = true; |
| 1255 | int err; | 1719 | int err; |
| 1256 | 1720 | ||
| 1257 | list_for_each_entry(call, &ftrace_events, list) { | 1721 | list_for_each_entry(call, &ftrace_events, list) { |
| 1258 | struct event_filter *filter = call->filter; | ||
| 1259 | 1722 | ||
| 1260 | if (strcmp(call->class->system, system->name) != 0) | 1723 | if (strcmp(call->class->system, system->name) != 0) |
| 1261 | continue; | 1724 | continue; |
| 1262 | 1725 | ||
| 1263 | /* try to see if the filter can be applied */ | 1726 | /* |
| 1264 | err = replace_preds(call, filter, ps, filter_string, true); | 1727 | * Try to see if the filter can be applied |
| 1728 | * (filter arg is ignored on dry_run) | ||
| 1729 | */ | ||
| 1730 | err = replace_preds(call, NULL, ps, filter_string, true); | ||
| 1265 | if (err) | 1731 | if (err) |
| 1732 | goto fail; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | list_for_each_entry(call, &ftrace_events, list) { | ||
| 1736 | struct event_filter *filter; | ||
| 1737 | |||
| 1738 | if (strcmp(call->class->system, system->name) != 0) | ||
| 1266 | continue; | 1739 | continue; |
| 1267 | 1740 | ||
| 1268 | /* really apply the filter */ | 1741 | filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL); |
| 1269 | filter_disable_preds(call); | 1742 | if (!filter_item) |
| 1270 | err = replace_preds(call, filter, ps, filter_string, false); | 1743 | goto fail_mem; |
| 1744 | |||
| 1745 | list_add_tail(&filter_item->list, &filter_list); | ||
| 1746 | |||
| 1747 | filter_item->filter = __alloc_filter(); | ||
| 1748 | if (!filter_item->filter) | ||
| 1749 | goto fail_mem; | ||
| 1750 | filter = filter_item->filter; | ||
| 1751 | |||
| 1752 | /* Can only fail on no memory */ | ||
| 1753 | err = replace_filter_string(filter, filter_string); | ||
| 1271 | if (err) | 1754 | if (err) |
| 1272 | filter_disable_preds(call); | 1755 | goto fail_mem; |
| 1273 | else { | 1756 | |
| 1757 | err = replace_preds(call, filter, ps, filter_string, false); | ||
| 1758 | if (err) { | ||
| 1759 | filter_disable(call); | ||
| 1760 | parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); | ||
| 1761 | append_filter_err(ps, filter); | ||
| 1762 | } else | ||
| 1274 | call->flags |= TRACE_EVENT_FL_FILTERED; | 1763 | call->flags |= TRACE_EVENT_FL_FILTERED; |
| 1275 | replace_filter_string(filter, filter_string); | 1764 | /* |
| 1276 | } | 1765 | * Regardless of if this returned an error, we still |
| 1766 | * replace the filter for the call. | ||
| 1767 | */ | ||
| 1768 | filter = call->filter; | ||
| 1769 | call->filter = filter_item->filter; | ||
| 1770 | filter_item->filter = filter; | ||
| 1771 | |||
| 1277 | fail = false; | 1772 | fail = false; |
| 1278 | } | 1773 | } |
| 1279 | 1774 | ||
| 1280 | if (fail) { | 1775 | if (fail) |
| 1281 | parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); | 1776 | goto fail; |
| 1282 | return -EINVAL; | 1777 | |
| 1778 | /* | ||
| 1779 | * The calls can still be using the old filters. | ||
| 1780 | * Do a synchronize_sched() to ensure all calls are | ||
| 1781 | * done with them before we free them. | ||
| 1782 | */ | ||
| 1783 | synchronize_sched(); | ||
| 1784 | list_for_each_entry_safe(filter_item, tmp, &filter_list, list) { | ||
| 1785 | __free_filter(filter_item->filter); | ||
| 1786 | list_del(&filter_item->list); | ||
| 1787 | kfree(filter_item); | ||
| 1283 | } | 1788 | } |
| 1284 | return 0; | 1789 | return 0; |
| 1790 | fail: | ||
| 1791 | /* No call succeeded */ | ||
| 1792 | list_for_each_entry_safe(filter_item, tmp, &filter_list, list) { | ||
| 1793 | list_del(&filter_item->list); | ||
| 1794 | kfree(filter_item); | ||
| 1795 | } | ||
| 1796 | parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); | ||
| 1797 | return -EINVAL; | ||
| 1798 | fail_mem: | ||
| 1799 | /* If any call succeeded, we still need to sync */ | ||
| 1800 | if (!fail) | ||
| 1801 | synchronize_sched(); | ||
| 1802 | list_for_each_entry_safe(filter_item, tmp, &filter_list, list) { | ||
| 1803 | __free_filter(filter_item->filter); | ||
| 1804 | list_del(&filter_item->list); | ||
| 1805 | kfree(filter_item); | ||
| 1806 | } | ||
| 1807 | return -ENOMEM; | ||
| 1285 | } | 1808 | } |
| 1286 | 1809 | ||
| 1287 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | 1810 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) |
| 1288 | { | 1811 | { |
| 1289 | int err; | ||
| 1290 | struct filter_parse_state *ps; | 1812 | struct filter_parse_state *ps; |
| 1813 | struct event_filter *filter; | ||
| 1814 | struct event_filter *tmp; | ||
| 1815 | int err = 0; | ||
| 1291 | 1816 | ||
| 1292 | mutex_lock(&event_mutex); | 1817 | mutex_lock(&event_mutex); |
| 1293 | 1818 | ||
| 1294 | err = init_preds(call); | ||
| 1295 | if (err) | ||
| 1296 | goto out_unlock; | ||
| 1297 | |||
| 1298 | if (!strcmp(strstrip(filter_string), "0")) { | 1819 | if (!strcmp(strstrip(filter_string), "0")) { |
| 1299 | filter_disable_preds(call); | 1820 | filter_disable(call); |
| 1300 | remove_filter_string(call->filter); | 1821 | filter = call->filter; |
| 1822 | if (!filter) | ||
| 1823 | goto out_unlock; | ||
| 1824 | call->filter = NULL; | ||
| 1825 | /* Make sure the filter is not being used */ | ||
| 1826 | synchronize_sched(); | ||
| 1827 | __free_filter(filter); | ||
| 1301 | goto out_unlock; | 1828 | goto out_unlock; |
| 1302 | } | 1829 | } |
| 1303 | 1830 | ||
| @@ -1306,22 +1833,41 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | |||
| 1306 | if (!ps) | 1833 | if (!ps) |
| 1307 | goto out_unlock; | 1834 | goto out_unlock; |
| 1308 | 1835 | ||
| 1309 | filter_disable_preds(call); | 1836 | filter = __alloc_filter(); |
| 1310 | replace_filter_string(call->filter, filter_string); | 1837 | if (!filter) { |
| 1838 | kfree(ps); | ||
| 1839 | goto out_unlock; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | replace_filter_string(filter, filter_string); | ||
| 1311 | 1843 | ||
| 1312 | parse_init(ps, filter_ops, filter_string); | 1844 | parse_init(ps, filter_ops, filter_string); |
| 1313 | err = filter_parse(ps); | 1845 | err = filter_parse(ps); |
| 1314 | if (err) { | 1846 | if (err) { |
| 1315 | append_filter_err(ps, call->filter); | 1847 | append_filter_err(ps, filter); |
| 1316 | goto out; | 1848 | goto out; |
| 1317 | } | 1849 | } |
| 1318 | 1850 | ||
| 1319 | err = replace_preds(call, call->filter, ps, filter_string, false); | 1851 | err = replace_preds(call, filter, ps, filter_string, false); |
| 1320 | if (err) | 1852 | if (err) { |
| 1321 | append_filter_err(ps, call->filter); | 1853 | filter_disable(call); |
| 1322 | else | 1854 | append_filter_err(ps, filter); |
| 1855 | } else | ||
| 1323 | call->flags |= TRACE_EVENT_FL_FILTERED; | 1856 | call->flags |= TRACE_EVENT_FL_FILTERED; |
| 1324 | out: | 1857 | out: |
| 1858 | /* | ||
| 1859 | * Always swap the call filter with the new filter | ||
| 1860 | * even if there was an error. If there was an error | ||
| 1861 | * in the filter, we disable the filter and show the error | ||
| 1862 | * string | ||
| 1863 | */ | ||
| 1864 | tmp = call->filter; | ||
| 1865 | call->filter = filter; | ||
| 1866 | if (tmp) { | ||
| 1867 | /* Make sure the call is done with the filter */ | ||
| 1868 | synchronize_sched(); | ||
| 1869 | __free_filter(tmp); | ||
| 1870 | } | ||
| 1325 | filter_opstack_clear(ps); | 1871 | filter_opstack_clear(ps); |
| 1326 | postfix_clear(ps); | 1872 | postfix_clear(ps); |
| 1327 | kfree(ps); | 1873 | kfree(ps); |
| @@ -1334,18 +1880,21 @@ out_unlock: | |||
| 1334 | int apply_subsystem_event_filter(struct event_subsystem *system, | 1880 | int apply_subsystem_event_filter(struct event_subsystem *system, |
| 1335 | char *filter_string) | 1881 | char *filter_string) |
| 1336 | { | 1882 | { |
| 1337 | int err; | ||
| 1338 | struct filter_parse_state *ps; | 1883 | struct filter_parse_state *ps; |
| 1884 | struct event_filter *filter; | ||
| 1885 | int err = 0; | ||
| 1339 | 1886 | ||
| 1340 | mutex_lock(&event_mutex); | 1887 | mutex_lock(&event_mutex); |
| 1341 | 1888 | ||
| 1342 | err = init_subsystem_preds(system); | ||
| 1343 | if (err) | ||
| 1344 | goto out_unlock; | ||
| 1345 | |||
| 1346 | if (!strcmp(strstrip(filter_string), "0")) { | 1889 | if (!strcmp(strstrip(filter_string), "0")) { |
| 1347 | filter_free_subsystem_preds(system); | 1890 | filter_free_subsystem_preds(system); |
| 1348 | remove_filter_string(system->filter); | 1891 | remove_filter_string(system->filter); |
| 1892 | filter = system->filter; | ||
| 1893 | system->filter = NULL; | ||
| 1894 | /* Ensure all filters are no longer used */ | ||
| 1895 | synchronize_sched(); | ||
| 1896 | filter_free_subsystem_filters(system); | ||
| 1897 | __free_filter(filter); | ||
| 1349 | goto out_unlock; | 1898 | goto out_unlock; |
| 1350 | } | 1899 | } |
| 1351 | 1900 | ||
| @@ -1354,7 +1903,17 @@ int apply_subsystem_event_filter(struct event_subsystem *system, | |||
| 1354 | if (!ps) | 1903 | if (!ps) |
| 1355 | goto out_unlock; | 1904 | goto out_unlock; |
| 1356 | 1905 | ||
| 1357 | replace_filter_string(system->filter, filter_string); | 1906 | filter = __alloc_filter(); |
| 1907 | if (!filter) | ||
| 1908 | goto out; | ||
| 1909 | |||
| 1910 | replace_filter_string(filter, filter_string); | ||
| 1911 | /* | ||
| 1912 | * No event actually uses the system filter | ||
| 1913 | * we can free it without synchronize_sched(). | ||
| 1914 | */ | ||
| 1915 | __free_filter(system->filter); | ||
| 1916 | system->filter = filter; | ||
| 1358 | 1917 | ||
| 1359 | parse_init(ps, filter_ops, filter_string); | 1918 | parse_init(ps, filter_ops, filter_string); |
| 1360 | err = filter_parse(ps); | 1919 | err = filter_parse(ps); |
| @@ -1384,7 +1943,7 @@ void ftrace_profile_free_filter(struct perf_event *event) | |||
| 1384 | struct event_filter *filter = event->filter; | 1943 | struct event_filter *filter = event->filter; |
| 1385 | 1944 | ||
| 1386 | event->filter = NULL; | 1945 | event->filter = NULL; |
| 1387 | __free_preds(filter); | 1946 | __free_filter(filter); |
| 1388 | } | 1947 | } |
| 1389 | 1948 | ||
| 1390 | int ftrace_profile_set_filter(struct perf_event *event, int event_id, | 1949 | int ftrace_profile_set_filter(struct perf_event *event, int event_id, |
| @@ -1410,8 +1969,8 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id, | |||
| 1410 | if (event->filter) | 1969 | if (event->filter) |
| 1411 | goto out_unlock; | 1970 | goto out_unlock; |
| 1412 | 1971 | ||
| 1413 | filter = __alloc_preds(); | 1972 | filter = __alloc_filter(); |
| 1414 | if (IS_ERR(filter)) { | 1973 | if (!filter) { |
| 1415 | err = PTR_ERR(filter); | 1974 | err = PTR_ERR(filter); |
| 1416 | goto out_unlock; | 1975 | goto out_unlock; |
| 1417 | } | 1976 | } |
| @@ -1419,7 +1978,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id, | |||
| 1419 | err = -ENOMEM; | 1978 | err = -ENOMEM; |
| 1420 | ps = kzalloc(sizeof(*ps), GFP_KERNEL); | 1979 | ps = kzalloc(sizeof(*ps), GFP_KERNEL); |
| 1421 | if (!ps) | 1980 | if (!ps) |
| 1422 | goto free_preds; | 1981 | goto free_filter; |
| 1423 | 1982 | ||
| 1424 | parse_init(ps, filter_ops, filter_str); | 1983 | parse_init(ps, filter_ops, filter_str); |
| 1425 | err = filter_parse(ps); | 1984 | err = filter_parse(ps); |
| @@ -1435,9 +1994,9 @@ free_ps: | |||
| 1435 | postfix_clear(ps); | 1994 | postfix_clear(ps); |
| 1436 | kfree(ps); | 1995 | kfree(ps); |
| 1437 | 1996 | ||
| 1438 | free_preds: | 1997 | free_filter: |
| 1439 | if (err) | 1998 | if (err) |
| 1440 | __free_preds(filter); | 1999 | __free_filter(filter); |
| 1441 | 2000 | ||
| 1442 | out_unlock: | 2001 | out_unlock: |
| 1443 | mutex_unlock(&event_mutex); | 2002 | mutex_unlock(&event_mutex); |
