tracing/filter: Change filter_match_preds function to use walk_pred_tree
authorJiri Olsa <jolsa@redhat.com>
Thu, 11 Aug 2011 14:25:53 +0000 (16:25 +0200)
committerSteven Rostedt <rostedt@goodmis.org>
Fri, 19 Aug 2011 18:35:58 +0000 (14:35 -0400)
Changing filter_match_preds function to use unified predicates tree
processing.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1313072754-4620-10-git-send-email-jolsa@redhat.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/trace_events_filter.c

index f44e68b89f15208b1ef7f19b5d0f19479d51b7af..319c3cac7d95e14f36476321a1708ed729911f23 100644 (file)
@@ -467,99 +467,91 @@ static int process_ops(struct filter_pred *preds,
 
        for (i = 0; i < op->val; i++) {
                pred = &preds[op->ops[i]];
-               match = pred->fn(pred, rec);
+               if (!WARN_ON_ONCE(!pred->fn))
+                       match = pred->fn(pred, rec);
                if (!!match == type)
                        return match;
        }
        return match;
 }
 
+struct filter_match_preds_data {
+       struct filter_pred *preds;
+       int match;
+       void *rec;
+};
+
+static int filter_match_preds_cb(enum move_type move, struct filter_pred *pred,
+                                int *err, void *data)
+{
+       struct filter_match_preds_data *d = data;
+
+       *err = 0;
+       switch (move) {
+       case MOVE_DOWN:
+               /* only AND and OR have children */
+               if (pred->left != FILTER_PRED_INVALID) {
+                       /* If ops is set, then it was folded. */
+                       if (!pred->ops)
+                               return WALK_PRED_DEFAULT;
+                       /* We can treat folded ops as a leaf node */
+                       d->match = process_ops(d->preds, pred, d->rec);
+               } else {
+                       if (!WARN_ON_ONCE(!pred->fn))
+                               d->match = pred->fn(pred, d->rec);
+               }
+
+               return WALK_PRED_PARENT;
+       case MOVE_UP_FROM_LEFT:
+               /*
+                * Check for short circuits.
+                *
+                * Optimization: !!match == (pred->op == OP_OR)
+                *   is the same as:
+                * if ((match && pred->op == OP_OR) ||
+                *     (!match && pred->op == OP_AND))
+                */
+               if (!!d->match == (pred->op == OP_OR))
+                       return WALK_PRED_PARENT;
+               break;
+       case MOVE_UP_FROM_RIGHT:
+               break;
+       }
+
+       return WALK_PRED_DEFAULT;
+}
+
 /* return 1 if event matches, 0 otherwise (discard) */
 int filter_match_preds(struct event_filter *filter, void *rec)
 {
-       int match = -1;
-       enum move_type move = MOVE_DOWN;
        struct filter_pred *preds;
-       struct filter_pred *pred;
        struct filter_pred *root;
-       int n_preds;
-       int done = 0;
+       struct filter_match_preds_data data = {
+               /* match is currently meaningless */
+               .match = -1,
+               .rec   = rec,
+       };
+       int n_preds, ret;
 
        /* no filter is considered a match */
        if (!filter)
                return 1;
 
        n_preds = filter->n_preds;
-
        if (!n_preds)
                return 1;
 
        /*
         * n_preds, root and filter->preds are protect with preemption disabled.
         */
-       preds = rcu_dereference_sched(filter->preds);
        root = rcu_dereference_sched(filter->root);
        if (!root)
                return 1;
 
-       pred = root;
-
-       /* match is currently meaningless */
-       match = -1;
-
-       do {
-               switch (move) {
-               case MOVE_DOWN:
-                       /* only AND and OR have children */
-                       if (pred->left != FILTER_PRED_INVALID) {
-                               /* If ops is set, then it was folded. */
-                               if (!pred->ops) {
-                                       /* keep going to down the left side */
-                                       pred = &preds[pred->left];
-                                       continue;
-                               }
-                               /* We can treat folded ops as a leaf node */
-                               match = process_ops(preds, pred, rec);
-                       } else
-                               match = pred->fn(pred, rec);
-                       /* If this pred is the only pred */
-                       if (pred == root)
-                               break;
-                       pred = get_pred_parent(pred, preds,
-                                              pred->parent, &move);
-                       continue;
-               case MOVE_UP_FROM_LEFT:
-                       /*
-                        * Check for short circuits.
-                        *
-                        * Optimization: !!match == (pred->op == OP_OR)
-                        *   is the same as:
-                        * if ((match && pred->op == OP_OR) ||
-                        *     (!match && pred->op == OP_AND))
-                        */
-                       if (!!match == (pred->op == OP_OR)) {
-                               if (pred == root)
-                                       break;
-                               pred = get_pred_parent(pred, preds,
-                                                      pred->parent, &move);
-                               continue;
-                       }
-                       /* now go down the right side of the tree. */
-                       pred = &preds[pred->right];
-                       move = MOVE_DOWN;
-                       continue;
-               case MOVE_UP_FROM_RIGHT:
-                       /* We finished this equation. */
-                       if (pred == root)
-                               break;
-                       pred = get_pred_parent(pred, preds,
-                                              pred->parent, &move);
-                       continue;
-               }
-               done = 1;
-       } while (!done);
-
-       return match;
+       data.preds = preds = rcu_dereference_sched(filter->preds);
+       ret = walk_pred_tree(preds, root, filter_match_preds_cb, &data);
+       WARN_ON(ret);
+       return data.match;
 }
 EXPORT_SYMBOL_GPL(filter_match_preds);