]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/trace/trace_events_filter.c
Merge tag 'powerpc-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
[linux.git] / kernel / trace / trace_events_filter.c
index 05a66493a1640ff9f5ae0b72c409231d367104ec..d3e59312ef405072e941464d5f66a8ef79433750 100644 (file)
@@ -66,7 +66,8 @@ static const char * ops[] = { OPS };
        C(INVALID_FILTER,       "Meaningless filter expression"),       \
        C(IP_FIELD_ONLY,        "Only 'ip' field is supported for function trace"), \
        C(INVALID_VALUE,        "Invalid value (did you forget quotes)?"), \
-       C(NO_FILTER,            "No filter found"),
+       C(ERRNO,                "Error"),                               \
+       C(NO_FILTER,            "No filter found")
 
 #undef C
 #define C(a, b)                FILT_ERR_##a
@@ -76,7 +77,7 @@ enum { ERRORS };
 #undef C
 #define C(a, b)                b
 
-static char *err_text[] = { ERRORS };
+static const char *err_text[] = { ERRORS };
 
 /* Called after a '!' character but "!=" and "!~" are not "not"s */
 static bool is_not(const char *str)
@@ -919,7 +920,8 @@ static void remove_filter_string(struct event_filter *filter)
        filter->filter_string = NULL;
 }
 
-static void append_filter_err(struct filter_parse_error *pe,
+static void append_filter_err(struct trace_array *tr,
+                             struct filter_parse_error *pe,
                              struct event_filter *filter)
 {
        struct trace_seq *s;
@@ -947,8 +949,14 @@ static void append_filter_err(struct filter_parse_error *pe,
        if (pe->lasterr > 0) {
                trace_seq_printf(s, "\n%*s", pos, "^");
                trace_seq_printf(s, "\nparse_error: %s\n", err_text[pe->lasterr]);
+               tracing_log_err(tr, "event filter parse error",
+                               filter->filter_string, err_text,
+                               pe->lasterr, pe->lasterr_pos);
        } else {
                trace_seq_printf(s, "\nError: (%d)\n", pe->lasterr);
+               tracing_log_err(tr, "event filter parse error",
+                               filter->filter_string, err_text,
+                               FILT_ERR_ERRNO, 0);
        }
        trace_seq_putc(s, 0);
        buf = kmemdup_nul(s->buffer, s->seq.len, GFP_KERNEL);
@@ -1214,30 +1222,30 @@ static int parse_pred(const char *str, void *data,
                 * (perf doesn't use it) and grab everything.
                 */
                if (strcmp(field->name, "ip") != 0) {
-                        parse_error(pe, FILT_ERR_IP_FIELD_ONLY, pos + i);
-                        goto err_free;
-                }
-                pred->fn = filter_pred_none;
-
-                /*
-                 * Quotes are not required, but if they exist then we need
-                 * to read them till we hit a matching one.
-                 */
-                if (str[i] == '\'' || str[i] == '"')
-                        q = str[i];
-                else
-                        q = 0;
-
-                for (i++; str[i]; i++) {
-                        if (q && str[i] == q)
-                                break;
-                        if (!q && (str[i] == ')' || str[i] == '&' ||
-                                   str[i] == '|'))
-                                break;
-                }
-                /* Skip quotes */
-                if (q)
-                        s++;
+                       parse_error(pe, FILT_ERR_IP_FIELD_ONLY, pos + i);
+                       goto err_free;
+               }
+               pred->fn = filter_pred_none;
+
+               /*
+                * Quotes are not required, but if they exist then we need
+                * to read them till we hit a matching one.
+                */
+               if (str[i] == '\'' || str[i] == '"')
+                       q = str[i];
+               else
+                       q = 0;
+
+               for (i++; str[i]; i++) {
+                       if (q && str[i] == q)
+                               break;
+                       if (!q && (str[i] == ')' || str[i] == '&' ||
+                                  str[i] == '|'))
+                               break;
+               }
+               /* Skip quotes */
+               if (q)
+                       s++;
                len = i - s;
                if (len >= MAX_FILTER_STR_VAL) {
                        parse_error(pe, FILT_ERR_OPERAND_TOO_LONG, pos + i);
@@ -1600,7 +1608,7 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
                if (err) {
                        filter_disable(file);
                        parse_error(pe, FILT_ERR_BAD_SUBSYS_FILTER, 0);
-                       append_filter_err(pe, filter);
+                       append_filter_err(tr, pe, filter);
                } else
                        event_set_filtered_flag(file);
 
@@ -1712,7 +1720,8 @@ static void create_filter_finish(struct filter_parse_error *pe)
  * information if @set_str is %true and the caller is responsible for
  * freeing it.
  */
-static int create_filter(struct trace_event_call *call,
+static int create_filter(struct trace_array *tr,
+                        struct trace_event_call *call,
                         char *filter_string, bool set_str,
                         struct event_filter **filterp)
 {
@@ -1729,17 +1738,18 @@ static int create_filter(struct trace_event_call *call,
 
        err = process_preds(call, filter_string, *filterp, pe);
        if (err && set_str)
-               append_filter_err(pe, *filterp);
+               append_filter_err(tr, pe, *filterp);
        create_filter_finish(pe);
 
        return err;
 }
 
-int create_event_filter(struct trace_event_call *call,
+int create_event_filter(struct trace_array *tr,
+                       struct trace_event_call *call,
                        char *filter_str, bool set_str,
                        struct event_filter **filterp)
 {
-       return create_filter(call, filter_str, set_str, filterp);
+       return create_filter(tr, call, filter_str, set_str, filterp);
 }
 
 /**
@@ -1766,7 +1776,7 @@ static int create_system_filter(struct trace_subsystem_dir *dir,
                        kfree((*filterp)->filter_string);
                        (*filterp)->filter_string = NULL;
                } else {
-                       append_filter_err(pe, *filterp);
+                       append_filter_err(tr, pe, *filterp);
                }
        }
        create_filter_finish(pe);
@@ -1797,7 +1807,7 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
                return 0;
        }
 
-       err = create_filter(call, filter_string, true, &filter);
+       err = create_filter(file->tr, call, filter_string, true, &filter);
 
        /*
         * Always swap the call filter with the new filter
@@ -2053,7 +2063,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
        if (event->filter)
                goto out_unlock;
 
-       err = create_filter(call, filter_str, false, &filter);
+       err = create_filter(NULL, call, filter_str, false, &filter);
        if (err)
                goto free_filter;
 
@@ -2202,8 +2212,8 @@ static __init int ftrace_test_event_filter(void)
                struct test_filter_data_t *d = &test_filter_data[i];
                int err;
 
-               err = create_filter(&event_ftrace_test_filter, d->filter,
-                                   false, &filter);
+               err = create_filter(NULL, &event_ftrace_test_filter,
+                                   d->filter, false, &filter);
                if (err) {
                        printk(KERN_INFO
                               "Failed to get filter for '%s', err %d\n",