gfp_t gfp_flags,
                                   int node)
 {
+       struct ftrace_event_call *call = &event_kmem_alloc;
        struct trace_array *tr = kmemtrace_array;
        struct kmemtrace_alloc_entry *entry;
        struct ring_buffer_event *event;
        entry->gfp_flags        = gfp_flags;
        entry->node             = node;
 
+       filter_check_discard(call, entry, event);
+
        ring_buffer_unlock_commit(tr->buffer, event);
 
        trace_wake_up();
                                  unsigned long call_site,
                                  const void *ptr)
 {
+       struct ftrace_event_call *call = &event_kmem_free;
        struct trace_array *tr = kmemtrace_array;
        struct kmemtrace_free_entry *entry;
        struct ring_buffer_event *event;
        entry->call_site        = call_site;
        entry->ptr              = ptr;
 
+       filter_check_discard(call, entry, event);
+
        ring_buffer_unlock_commit(tr->buffer, event);
 
        trace_wake_up();
 
               unsigned long ip, unsigned long parent_ip, unsigned long flags,
               int pc)
 {
+       struct ftrace_event_call *call = &event_function;
        struct ring_buffer_event *event;
        struct ftrace_entry *entry;
 
        entry   = ring_buffer_event_data(event);
        entry->ip                       = ip;
        entry->parent_ip                = parent_ip;
+
+       filter_check_discard(call, entry, event);
+
        ring_buffer_unlock_commit(tr->buffer, event);
 }
 
                                unsigned long flags,
                                int pc)
 {
+       struct ftrace_event_call *call = &event_funcgraph_entry;
        struct ring_buffer_event *event;
        struct ftrace_graph_ent_entry *entry;
 
                return 0;
        entry   = ring_buffer_event_data(event);
        entry->graph_ent                        = *trace;
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(global_trace.buffer, event);
 
        return 1;
                                unsigned long flags,
                                int pc)
 {
+       struct ftrace_event_call *call = &event_funcgraph_exit;
        struct ring_buffer_event *event;
        struct ftrace_graph_ret_entry *entry;
 
                return;
        entry   = ring_buffer_event_data(event);
        entry->ret                              = *trace;
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(global_trace.buffer, event);
 }
 #endif
                                 int skip, int pc)
 {
 #ifdef CONFIG_STACKTRACE
+       struct ftrace_event_call *call = &event_kernel_stack;
        struct ring_buffer_event *event;
        struct stack_entry *entry;
        struct stack_trace trace;
        trace.entries           = entry->caller;
 
        save_stack_trace(&trace);
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(tr->buffer, event);
 #endif
 }
                                   unsigned long flags, int pc)
 {
 #ifdef CONFIG_STACKTRACE
+       struct ftrace_event_call *call = &event_user_stack;
        struct ring_buffer_event *event;
        struct userstack_entry *entry;
        struct stack_trace trace;
        trace.entries           = entry->caller;
 
        save_stack_trace_user(&trace);
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(tr->buffer, event);
 #endif
 }
                     unsigned long arg1, unsigned long arg2, unsigned long arg3,
                     int pc)
 {
+       struct ftrace_event_call *call = &event_special;
        struct ring_buffer_event *event;
        struct trace_array *tr = __tr;
        struct special_entry *entry;
        entry->arg1                     = arg1;
        entry->arg2                     = arg2;
        entry->arg3                     = arg3;
+       filter_check_discard(call, entry, event);
        trace_buffer_unlock_commit(tr, event, 0, pc);
 }
 
                           struct task_struct *next,
                           unsigned long flags, int pc)
 {
+       struct ftrace_event_call *call = &event_context_switch;
        struct ring_buffer_event *event;
        struct ctx_switch_entry *entry;
 
        entry->next_prio                = next->prio;
        entry->next_state               = next->state;
        entry->next_cpu = task_cpu(next);
+
+       filter_check_discard(call, entry, event);
+
        trace_buffer_unlock_commit(tr, event, flags, pc);
 }
 
                           struct task_struct *curr,
                           unsigned long flags, int pc)
 {
+       struct ftrace_event_call *call = &event_wakeup;
        struct ring_buffer_event *event;
        struct ctx_switch_entry *entry;
 
        entry->next_state               = wakee->state;
        entry->next_cpu                 = task_cpu(wakee);
 
+       filter_check_discard(call, entry, event);
+
        ring_buffer_unlock_commit(tr->buffer, event);
        ftrace_trace_stack(tr, flags, 6, pc);
        ftrace_trace_userstack(tr, flags, pc);
                (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
        static u32 trace_buf[TRACE_BUF_SIZE];
 
+       struct ftrace_event_call *call = &event_bprint;
        struct ring_buffer_event *event;
        struct trace_array *tr = &global_trace;
        struct trace_array_cpu *data;
        entry->fmt                      = fmt;
 
        memcpy(entry->buf, trace_buf, sizeof(u32) * len);
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(tr->buffer, event);
 
 out_unlock:
        static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
        static char trace_buf[TRACE_BUF_SIZE];
 
+       struct ftrace_event_call *call = &event_print;
        struct ring_buffer_event *event;
        struct trace_array *tr = &global_trace;
        struct trace_array_cpu *data;
 
        memcpy(&entry->buf, trace_buf, len);
        entry->buf[len] = 0;
+       filter_check_discard(call, entry, event);
        ring_buffer_unlock_commit(tr->buffer, event);
 
  out_unlock:
 
 extern int filter_add_subsystem_pred(struct event_subsystem *system,
                                     struct filter_pred *pred);
 
+static inline void
+filter_check_discard(struct ftrace_event_call *call, void *rec,
+                    struct ring_buffer_event *event)
+{
+       if (unlikely(call->preds) && !filter_match_preds(call, rec))
+               ring_buffer_event_discard(event);
+}
+
+#define __common_field(type, item)                                     \
+       ret = trace_define_field(event_call, #type, "common_" #item,    \
+                                offsetof(typeof(field.ent), item),     \
+                                sizeof(field.ent.item));               \
+       if (ret)                                                        \
+               return ret;
+
 void event_trace_printk(unsigned long ip, const char *fmt, ...);
 extern struct ftrace_event_call __start_ftrace_events[];
 extern struct ftrace_event_call __stop_ftrace_events[];
                __trace_printk(ip, fmt, ##args);                        \
 } while (0)
 
+#undef TRACE_EVENT_FORMAT
+#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)     \
+       extern struct ftrace_event_call event_##call;
+#include "trace_event_types.h"
+
 #endif /* _LINUX_KERNEL_TRACE_H */
 
 static void
 probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
 {
+       struct ftrace_event_call *call = &event_branch;
        struct trace_array *tr = branch_tracer;
        struct ring_buffer_event *event;
        struct trace_branch *entry;
        entry->line = f->line;
        entry->correct = val == expect;
 
+       filter_check_discard(call, entry, event);
+
        ring_buffer_unlock_commit(tr->buffer, event);
 
  out:
 
 TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
        TRACE_STRUCT(
                TRACE_FIELD(unsigned int, line, line)
-               TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func, func)
-               TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file, file)
+               TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func,
+                                   TRACE_FUNC_SIZE+1, func)
+               TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file,
+                                   TRACE_FUNC_SIZE+1, file)
                TRACE_FIELD(char, correct, correct)
        ),
        TP_RAW_FMT("%u:%s:%s (%u)")
 
 event_subsystem_dir(const char *name, struct dentry *d_events)
 {
        struct event_subsystem *system;
+       struct dentry *entry;
 
        /* First see if we did not already create this dir */
        list_for_each_entry(system, &event_subsystems, list) {
 
        system->preds = NULL;
 
+       entry = debugfs_create_file("filter", 0644, system->entry, system,
+                                   &ftrace_subsystem_filter_fops);
+       if (!entry)
+               pr_warning("Could not create debugfs "
+                          "'%s/filter' entry\n", name);
+
        return system->entry;
 }
 
 
        }
 
        events_for_each(call) {
-               if (!call->name || !call->regfunc)
+               if (!call->define_fields)
                        continue;
 
                if (!strcmp(call->system, system->name))
        events_for_each(call) {
                int err;
 
-               if (!call->name || !call->regfunc)
+               if (!call->define_fields)
                        continue;
 
                if (strcmp(call->system, system->name))
 
        if (ret)                                                        \
                return ret;
 
-#define __common_field(type, item)                                     \
-       ret = trace_define_field(event_call, #type, "common_" #item,    \
-                                offsetof(typeof(field.ent), item),     \
-                                sizeof(field.ent.item));               \
-       if (ret)                                                        \
-               return ret;
-
 #undef TRACE_EVENT
 #define TRACE_EVENT(call, proto, args, tstruct, func, print)           \
 int                                                                    \
 
 
 
 #undef TRACE_FIELD_SPECIAL
-#define TRACE_FIELD_SPECIAL(type_item, item, cmd)                      \
+#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd)                 \
        ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t"   \
                               "offset:%u;\tsize:%u;\n",                \
                               (unsigned int)offsetof(typeof(field), item), \
 #define TRACE_ENTRY    entry
 
 #undef TRACE_FIELD_SPECIAL
-#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
+#define TRACE_FIELD_SPECIAL(type_item, item, len, cmd) \
        cmd;
 
 #undef TRACE_EVENT_FORMAT
 #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)     \
+int ftrace_define_fields_##call(void);                                 \
+static int ftrace_raw_init_event_##call(void);                         \
                                                                        \
-static struct ftrace_event_call __used                                 \
+struct ftrace_event_call __used                                                \
 __attribute__((__aligned__(4)))                                                \
 __attribute__((section("_ftrace_events"))) event_##call = {            \
        .name                   = #call,                                \
        .id                     = proto,                                \
        .system                 = __stringify(TRACE_SYSTEM),            \
+       .raw_init               = ftrace_raw_init_event_##call,         \
        .show_format            = ftrace_format_##call,                 \
+       .define_fields          = ftrace_define_fields_##call,          \
+};                                                                     \
+static int ftrace_raw_init_event_##call(void)                          \
+{                                                                      \
+       INIT_LIST_HEAD(&event_##call.fields);                           \
+       return 0;                                                       \
+}                                                                      \
+
+#include "trace_event_types.h"
+
+#undef TRACE_FIELD
+#define TRACE_FIELD(type, item, assign)                                        \
+       ret = trace_define_field(event_call, #type, #item,              \
+                                offsetof(typeof(field), item),         \
+                                sizeof(field.item));                   \
+       if (ret)                                                        \
+               return ret;
+
+#undef TRACE_FIELD_SPECIAL
+#define TRACE_FIELD_SPECIAL(type, item, len, cmd)                      \
+       ret = trace_define_field(event_call, #type "[" #len "]", #item, \
+                                offsetof(typeof(field), item),         \
+                                sizeof(field.item));                   \
+       if (ret)                                                        \
+               return ret;
+
+#undef TRACE_FIELD_ZERO_CHAR
+#define TRACE_FIELD_ZERO_CHAR(item)
+
+#undef TRACE_EVENT_FORMAT
+#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)     \
+int                                                                    \
+ftrace_define_fields_##call(void)                                      \
+{                                                                      \
+       struct ftrace_event_call *event_call = &event_##call;           \
+       struct args field;                                              \
+       int ret;                                                        \
+                                                                       \
+       __common_field(unsigned char, type);                            \
+       __common_field(unsigned char, flags);                           \
+       __common_field(unsigned char, preempt_count);                   \
+       __common_field(int, pid);                                       \
+       __common_field(int, tgid);                                      \
+                                                                       \
+       tstruct;                                                        \
+                                                                       \
+       return ret;                                                     \
 }
+
 #include "trace_event_types.h"
 
 
 void trace_hw_branch(u64 from, u64 to)
 {
+       struct ftrace_event_call *call = &event_hw_branch;
        struct trace_array *tr = hw_branch_trace;
        struct ring_buffer_event *event;
        struct hw_branch_entry *entry;
        entry->ent.type = TRACE_HW_BRANCHES;
        entry->from = from;
        entry->to   = to;
+       filter_check_discard(call, entry, event);
        trace_buffer_unlock_commit(tr, event, 0, 0);
 
  out:
 
 
 static void probe_power_end(struct power_trace *it)
 {
+       struct ftrace_event_call *call = &event_power;
        struct ring_buffer_event *event;
        struct trace_power *entry;
        struct trace_array_cpu *data;
                goto out;
        entry   = ring_buffer_event_data(event);
        entry->state_data = *it;
+       filter_check_discard(call, entry, event);
        trace_buffer_unlock_commit(tr, event, 0, 0);
  out:
        preempt_enable();
 static void probe_power_mark(struct power_trace *it, unsigned int type,
                                unsigned int level)
 {
+       struct ftrace_event_call *call = &event_power;
        struct ring_buffer_event *event;
        struct trace_power *entry;
        struct trace_array_cpu *data;
                goto out;
        entry   = ring_buffer_event_data(event);
        entry->state_data = *it;
+       filter_check_discard(call, entry, event);
        trace_buffer_unlock_commit(tr, event, 0, 0);
  out:
        preempt_enable();