]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - kernel/trace/trace_kprobe.c
tracing: Allow events to share their print functions
[net-next-2.6.git] / kernel / trace / trace_kprobe.c
index 505c92273b1a51b98370221dcd30cd9234d36d06..b989ae229a200239760b15f48886833e52fc61d1 100644 (file)
@@ -202,6 +202,7 @@ struct trace_probe {
        unsigned long           nhit;
        unsigned int            flags;  /* For TP_FLAG_* */
        const char              *symbol;        /* symbol name */
+       struct ftrace_event_class       class;
        struct ftrace_event_call        call;
        struct trace_event              event;
        unsigned int            nr_args;
@@ -323,6 +324,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
                goto error;
        }
 
+       tp->call.class = &tp->class;
        tp->call.name = kstrdup(event, GFP_KERNEL);
        if (!tp->call.name)
                goto error;
@@ -332,8 +334,8 @@ static struct trace_probe *alloc_trace_probe(const char *group,
                goto error;
        }
 
-       tp->call.system = kstrdup(group, GFP_KERNEL);
-       if (!tp->call.system)
+       tp->class.system = kstrdup(group, GFP_KERNEL);
+       if (!tp->class.system)
                goto error;
 
        INIT_LIST_HEAD(&tp->list);
@@ -361,7 +363,7 @@ static void free_trace_probe(struct trace_probe *tp)
        for (i = 0; i < tp->nr_args; i++)
                free_probe_arg(&tp->args[i]);
 
-       kfree(tp->call.system);
+       kfree(tp->call.class->system);
        kfree(tp->call.name);
        kfree(tp->symbol);
        kfree(tp);
@@ -374,7 +376,7 @@ static struct trace_probe *find_probe_event(const char *event,
 
        list_for_each_entry(tp, &probe_list, list)
                if (strcmp(tp->call.name, event) == 0 &&
-                   strcmp(tp->call.system, group) == 0)
+                   strcmp(tp->call.class->system, group) == 0)
                        return tp;
        return NULL;
 }
@@ -399,7 +401,7 @@ static int register_trace_probe(struct trace_probe *tp)
        mutex_lock(&probe_lock);
 
        /* register as an event */
-       old_tp = find_probe_event(tp->call.name, tp->call.system);
+       old_tp = find_probe_event(tp->call.name, tp->call.class->system);
        if (old_tp) {
                /* delete old event */
                unregister_trace_probe(old_tp);
@@ -798,7 +800,7 @@ static int probes_seq_show(struct seq_file *m, void *v)
        char buf[MAX_ARGSTR_LEN + 1];
 
        seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p');
-       seq_printf(m, ":%s/%s", tp->call.system, tp->call.name);
+       seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name);
 
        if (!tp->symbol)
                seq_printf(m, " 0x%p", tp->rp.kp.addr);
@@ -1009,16 +1011,15 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
 
 /* Event entry printers */
 enum print_line_t
-print_kprobe_event(struct trace_iterator *iter, int flags)
+print_kprobe_event(struct trace_iterator *iter, int flags,
+                  struct trace_event *event)
 {
        struct kprobe_trace_entry *field;
        struct trace_seq *s = &iter->seq;
-       struct trace_event *event;
        struct trace_probe *tp;
        int i;
 
        field = (struct kprobe_trace_entry *)iter->ent;
-       event = ftrace_find_event(field->ent.type);
        tp = container_of(event, struct trace_probe, event);
 
        if (!trace_seq_printf(s, "%s: (", tp->call.name))
@@ -1044,16 +1045,15 @@ partial:
 }
 
 enum print_line_t
-print_kretprobe_event(struct trace_iterator *iter, int flags)
+print_kretprobe_event(struct trace_iterator *iter, int flags,
+                     struct trace_event *event)
 {
        struct kretprobe_trace_entry *field;
        struct trace_seq *s = &iter->seq;
-       struct trace_event *event;
        struct trace_probe *tp;
        int i;
 
        field = (struct kretprobe_trace_entry *)iter->ent;
-       event = ftrace_find_event(field->ent.type);
        tp = container_of(event, struct trace_probe, event);
 
        if (!trace_seq_printf(s, "%s: (", tp->call.name))
@@ -1110,8 +1110,6 @@ static void probe_event_disable(struct ftrace_event_call *call)
 
 static int probe_event_raw_init(struct ftrace_event_call *event_call)
 {
-       INIT_LIST_HEAD(&event_call->fields);
-
        return 0;
 }
 
@@ -1214,7 +1212,7 @@ static int set_print_fmt(struct trace_probe *tp)
 #ifdef CONFIG_PERF_EVENTS
 
 /* Kprobe profile handler */
-static __kprobes void kprobe_profile_func(struct kprobe *kp,
+static __kprobes void kprobe_perf_func(struct kprobe *kp,
                                         struct pt_regs *regs)
 {
        struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
@@ -1227,11 +1225,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp,
        __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);
        size = ALIGN(__size + sizeof(u32), sizeof(u64));
        size -= sizeof(u32);
-       if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE,
+       if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
                     "profile buffer not large enough"))
                return;
 
-       entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags);
+       entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags);
        if (!entry)
                return;
 
@@ -1240,11 +1238,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp,
        for (i = 0; i < tp->nr_args; i++)
                entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
 
-       ftrace_perf_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags);
+       perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs);
 }
 
 /* Kretprobe profile handler */
-static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,
+static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
                                            struct pt_regs *regs)
 {
        struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
@@ -1257,11 +1255,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,
        __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);
        size = ALIGN(__size + sizeof(u32), sizeof(u64));
        size -= sizeof(u32);
-       if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE,
+       if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
                     "profile buffer not large enough"))
                return;
 
-       entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags);
+       entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags);
        if (!entry)
                return;
 
@@ -1271,10 +1269,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,
        for (i = 0; i < tp->nr_args; i++)
                entry->args[i] = call_fetch(&tp->args[i].fetch, regs);
 
-       ftrace_perf_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags);
+       perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1,
+                              irq_flags, regs);
 }
 
-static int probe_profile_enable(struct ftrace_event_call *call)
+static int probe_perf_enable(struct ftrace_event_call *call)
 {
        struct trace_probe *tp = (struct trace_probe *)call->data;
 
@@ -1286,7 +1285,7 @@ static int probe_profile_enable(struct ftrace_event_call *call)
                return enable_kprobe(&tp->rp.kp);
 }
 
-static void probe_profile_disable(struct ftrace_event_call *call)
+static void probe_perf_disable(struct ftrace_event_call *call)
 {
        struct trace_probe *tp = (struct trace_probe *)call->data;
 
@@ -1301,6 +1300,26 @@ static void probe_profile_disable(struct ftrace_event_call *call)
 }
 #endif /* CONFIG_PERF_EVENTS */
 
+static __kprobes
+int kprobe_register(struct ftrace_event_call *event, enum trace_reg type)
+{
+       switch (type) {
+       case TRACE_REG_REGISTER:
+               return probe_event_enable(event);
+       case TRACE_REG_UNREGISTER:
+               probe_event_disable(event);
+               return 0;
+
+#ifdef CONFIG_PERF_EVENTS
+       case TRACE_REG_PERF_REGISTER:
+               return probe_perf_enable(event);
+       case TRACE_REG_PERF_UNREGISTER:
+               probe_perf_disable(event);
+               return 0;
+#endif
+       }
+       return 0;
+}
 
 static __kprobes
 int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
@@ -1311,7 +1330,7 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
                kprobe_trace_func(kp, regs);
 #ifdef CONFIG_PERF_EVENTS
        if (tp->flags & TP_FLAG_PROFILE)
-               kprobe_profile_func(kp, regs);
+               kprobe_perf_func(kp, regs);
 #endif
        return 0;       /* We don't tweek kernel, so just return 0 */
 }
@@ -1325,11 +1344,19 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
                kretprobe_trace_func(ri, regs);
 #ifdef CONFIG_PERF_EVENTS
        if (tp->flags & TP_FLAG_PROFILE)
-               kretprobe_profile_func(ri, regs);
+               kretprobe_perf_func(ri, regs);
 #endif
        return 0;       /* We don't tweek kernel, so just return 0 */
 }
 
+static struct trace_event_functions kretprobe_funcs = {
+       .trace          = print_kretprobe_event
+};
+
+static struct trace_event_functions kprobe_funcs = {
+       .trace          = print_kprobe_event
+};
+
 static int register_probe_event(struct trace_probe *tp)
 {
        struct ftrace_event_call *call = &tp->call;
@@ -1337,13 +1364,15 @@ static int register_probe_event(struct trace_probe *tp)
 
        /* Initialize ftrace_event_call */
        if (probe_is_return(tp)) {
-               tp->event.trace = print_kretprobe_event;
-               call->raw_init = probe_event_raw_init;
-               call->define_fields = kretprobe_event_define_fields;
+               tp->event.funcs = &kretprobe_funcs;
+               INIT_LIST_HEAD(&call->class->fields);
+               call->class->raw_init = probe_event_raw_init;
+               call->class->define_fields = kretprobe_event_define_fields;
        } else {
-               tp->event.trace = print_kprobe_event;
-               call->raw_init = probe_event_raw_init;
-               call->define_fields = kprobe_event_define_fields;
+               INIT_LIST_HEAD(&call->class->fields);
+               tp->event.funcs = &kprobe_funcs;
+               call->class->raw_init = probe_event_raw_init;
+               call->class->define_fields = kprobe_event_define_fields;
        }
        if (set_print_fmt(tp) < 0)
                return -ENOMEM;
@@ -1354,13 +1383,7 @@ static int register_probe_event(struct trace_probe *tp)
                return -ENODEV;
        }
        call->enabled = 0;
-       call->regfunc = probe_event_enable;
-       call->unregfunc = probe_event_disable;
-
-#ifdef CONFIG_PERF_EVENTS
-       call->profile_enable = probe_profile_enable;
-       call->profile_disable = probe_profile_disable;
-#endif
+       call->class->reg = kprobe_register;
        call->data = tp;
        ret = trace_add_event_call(call);
        if (ret) {