lkml.org 
[lkml]   [2009]   [Jul]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH -tip -v12 06/11] tracing: ftrace dynamic ftrace_event_call support
    Date
    Add dynamic ftrace_event_call support to ftrace. Trace engines can adds new
    ftrace_event_call to ftrace on the fly. Each operator functions of the call
    takes a ftrace_event_call data structure as an argument, because these
    functions may be shared among several ftrace_event_calls.

    Changes from v11:
    - Call remove_subsystem_dir() when unregistering an event call.

    Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
    Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: Tom Zanussi <tzanussi@gmail.com>
    ---
    include/linux/ftrace_event.h | 13 +++++---
    include/trace/ftrace.h | 22 ++++++-------
    kernel/trace/trace_events.c | 72 ++++++++++++++++++++++++++++++++----------
    kernel/trace/trace_export.c | 27 ++++++++--------
    4 files changed, 86 insertions(+), 48 deletions(-)
    diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
    index 5c093ff..f7733b6 100644
    --- a/include/linux/ftrace_event.h
    +++ b/include/linux/ftrace_event.h
    @@ -108,12 +108,13 @@ struct ftrace_event_call {
    struct dentry *dir;
    struct trace_event *event;
    int enabled;
    - int (*regfunc)(void);
    - void (*unregfunc)(void);
    + int (*regfunc)(struct ftrace_event_call *);
    + void (*unregfunc)(struct ftrace_event_call *);
    int id;
    - int (*raw_init)(void);
    - int (*show_format)(struct trace_seq *s);
    - int (*define_fields)(void);
    + int (*raw_init)(struct ftrace_event_call *);
    + int (*show_format)(struct ftrace_event_call *,
    + struct trace_seq *);
    + int (*define_fields)(struct ftrace_event_call *);
    struct list_head fields;
    int filter_active;
    void *filter;
    @@ -138,6 +139,8 @@ extern int filter_current_check_discard(struct ftrace_event_call *call,

    extern int trace_define_field(struct ftrace_event_call *call, char *type,
    char *name, int offset, int size, int is_signed);
    +extern int trace_add_event_call(struct ftrace_event_call *call);
    +extern void trace_remove_event_call(struct ftrace_event_call *call);

    #define is_signed_type(type) (((type)(-1)) < 0)

    diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
    index 1867553..d696580 100644
    --- a/include/trace/ftrace.h
    +++ b/include/trace/ftrace.h
    @@ -147,7 +147,8 @@
    #undef TRACE_EVENT
    #define TRACE_EVENT(call, proto, args, tstruct, func, print) \
    static int \
    -ftrace_format_##call(struct trace_seq *s) \
    +ftrace_format_##call(struct ftrace_event_call *event_call, \
    + struct trace_seq *s) \
    { \
    struct ftrace_raw_##call field __attribute__((unused)); \
    int ret = 0; \
    @@ -289,10 +290,9 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
    #undef TRACE_EVENT
    #define TRACE_EVENT(call, proto, args, tstruct, func, print) \
    int \
    -ftrace_define_fields_##call(void) \
    +ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
    { \
    struct ftrace_raw_##call field; \
    - struct ftrace_event_call *event_call = &event_##call; \
    int ret; \
    \
    __common_field(int, type, 1); \
    @@ -355,7 +355,7 @@ static inline int ftrace_get_offsets_##call( \
    * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
    * }
    *
    - * static int ftrace_reg_event_<call>(void)
    + * static int ftrace_reg_event_<call>(struct ftrace_event_call *unused)
    * {
    * int ret;
    *
    @@ -366,7 +366,7 @@ static inline int ftrace_get_offsets_##call( \
    * return ret;
    * }
    *
    - * static void ftrace_unreg_event_<call>(void)
    + * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
    * {
    * unregister_trace_<call>(ftrace_event_<call>);
    * }
    @@ -399,7 +399,7 @@ static inline int ftrace_get_offsets_##call( \
    * trace_current_buffer_unlock_commit(event, irq_flags, pc);
    * }
    *
    - * static int ftrace_raw_reg_event_<call>(void)
    + * static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused)
    * {
    * int ret;
    *
    @@ -410,7 +410,7 @@ static inline int ftrace_get_offsets_##call( \
    * return ret;
    * }
    *
    - * static void ftrace_unreg_event_<call>(void)
    + * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
    * {
    * unregister_trace_<call>(ftrace_raw_event_<call>);
    * }
    @@ -419,7 +419,7 @@ static inline int ftrace_get_offsets_##call( \
    * .trace = ftrace_raw_output_<call>, <-- stage 2
    * };
    *
    - * static int ftrace_raw_init_event_<call>(void)
    + * static int ftrace_raw_init_event_<call>(struct ftrace_event_call *unused)
    * {
    * int id;
    *
    @@ -537,7 +537,7 @@ static void ftrace_raw_event_##call(proto) \
    trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
    } \
    \
    -static int ftrace_raw_reg_event_##call(void) \
    +static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
    { \
    int ret; \
    \
    @@ -548,7 +548,7 @@ static int ftrace_raw_reg_event_##call(void) \
    return ret; \
    } \
    \
    -static void ftrace_raw_unreg_event_##call(void) \
    +static void ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused)\
    { \
    unregister_trace_##call(ftrace_raw_event_##call); \
    } \
    @@ -557,7 +557,7 @@ static struct trace_event ftrace_event_type_##call = { \
    .trace = ftrace_raw_output_##call, \
    }; \
    \
    -static int ftrace_raw_init_event_##call(void) \
    +static int ftrace_raw_init_event_##call(struct ftrace_event_call *unused)\
    { \
    int id; \
    \
    diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
    index 90cf936..174840b 100644
    --- a/kernel/trace/trace_events.c
    +++ b/kernel/trace/trace_events.c
    @@ -62,9 +62,7 @@ err:
    }
    EXPORT_SYMBOL_GPL(trace_define_field);

    -#ifdef CONFIG_MODULES
    -
    -static void trace_destroy_fields(struct ftrace_event_call *call)
    +void trace_destroy_fields(struct ftrace_event_call *call)
    {
    struct ftrace_event_field *field, *next;

    @@ -76,8 +74,6 @@ static void trace_destroy_fields(struct ftrace_event_call *call)
    }
    }

    -#endif /* CONFIG_MODULES */
    -
    static void ftrace_event_enable_disable(struct ftrace_event_call *call,
    int enable)
    {
    @@ -86,14 +82,14 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
    if (call->enabled) {
    call->enabled = 0;
    tracing_stop_cmdline_record();
    - call->unregfunc();
    + call->unregfunc(call);
    }
    break;
    case 1:
    if (!call->enabled) {
    call->enabled = 1;
    tracing_start_cmdline_record();
    - call->regfunc();
    + call->regfunc(call);
    }
    break;
    }
    @@ -576,7 +572,7 @@ event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
    trace_seq_printf(s, "format:\n");
    trace_write_header(s);

    - r = call->show_format(s);
    + r = call->show_format(call, s);
    if (!r) {
    /*
    * ug! The format output is bigger than a PAGE!!
    @@ -952,7 +948,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
    d_events = event_subsystem_dir(call->system, d_events);

    if (call->raw_init) {
    - ret = call->raw_init();
    + ret = call->raw_init(call);
    if (ret < 0) {
    pr_warning("Could not initialize trace point"
    " events/%s\n", call->name);
    @@ -976,7 +972,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
    id);

    if (call->define_fields) {
    - ret = call->define_fields();
    + ret = call->define_fields(call);
    if (ret < 0) {
    pr_warning("Could not initialize trace point"
    " events/%s\n", call->name);
    @@ -996,6 +992,53 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
    return 0;
    }

    +static int __trace_add_event_call(struct ftrace_event_call *call)
    +{
    + struct dentry *d_events;
    +
    + if (!call->name)
    + return -EINVAL;
    +
    + d_events = event_trace_events_dir();
    + if (!d_events)
    + return -ENOENT;
    +
    + list_add(&call->list, &ftrace_events);
    + return event_create_dir(call, d_events, &ftrace_event_id_fops,
    + &ftrace_enable_fops, &ftrace_event_filter_fops,
    + &ftrace_event_format_fops);
    +}
    +
    +/* Add an additional event_call dynamically */
    +int trace_add_event_call(struct ftrace_event_call *call)
    +{
    + int ret;
    + mutex_lock(&event_mutex);
    + ret = __trace_add_event_call(call);
    + mutex_unlock(&event_mutex);
    + return ret;
    +}
    +
    +static void __trace_remove_event_call(struct ftrace_event_call *call)
    +{
    + ftrace_event_enable_disable(call, 0);
    + if (call->event)
    + __unregister_ftrace_event(call->event);
    + debugfs_remove_recursive(call->dir);
    + list_del(&call->list);
    + trace_destroy_fields(call);
    + destroy_preds(call);
    + remove_subsystem_dir(call->system);
    +}
    +
    +/* Remove an event_call */
    +void trace_remove_event_call(struct ftrace_event_call *call)
    +{
    + mutex_lock(&event_mutex);
    + __trace_remove_event_call(call);
    + mutex_unlock(&event_mutex);
    +}
    +
    #define for_each_event(event, start, end) \
    for (event = start; \
    (unsigned long)event < (unsigned long)end; \
    @@ -1101,14 +1144,7 @@ static void trace_module_remove_events(struct module *mod)
    list_for_each_entry_safe(call, p, &ftrace_events, list) {
    if (call->mod == mod) {
    found = true;
    - ftrace_event_enable_disable(call, 0);
    - if (call->event)
    - __unregister_ftrace_event(call->event);
    - debugfs_remove_recursive(call->dir);
    - list_del(&call->list);
    - trace_destroy_fields(call);
    - destroy_preds(call);
    - remove_subsystem_dir(call->system);
    + __trace_remove_event_call(call);
    }
    }

    diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
    index d06cf89..7cee79d 100644
    --- a/kernel/trace/trace_export.c
    +++ b/kernel/trace/trace_export.c
    @@ -60,7 +60,7 @@ extern void __bad_type_size(void);
    #undef TRACE_EVENT_FORMAT
    #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
    static int \
    -ftrace_format_##call(struct trace_seq *s) \
    +ftrace_format_##call(struct ftrace_event_call *dummy, struct trace_seq *s)\
    { \
    struct args field; \
    int ret; \
    @@ -76,7 +76,7 @@ ftrace_format_##call(struct trace_seq *s) \
    #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \
    tpfmt) \
    static int \
    -ftrace_format_##call(struct trace_seq *s) \
    +ftrace_format_##call(struct ftrace_event_call *dummy, struct trace_seq *s)\
    { \
    struct args field; \
    int ret; \
    @@ -115,10 +115,16 @@ ftrace_format_##call(struct trace_seq *s) \
    #define TRACE_FIELD_SPECIAL(type_item, item, len, cmd) \
    cmd;

    +static int ftrace_raw_init_event(struct ftrace_event_call *event_call)
    +{
    + INIT_LIST_HEAD(&event_call->fields);
    + init_preds(event_call);
    + return 0;
    +}
    +
    #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); \
    +int ftrace_define_fields_##call(struct ftrace_event_call *c); \
    \
    struct ftrace_event_call __used \
    __attribute__((__aligned__(4))) \
    @@ -126,16 +132,10 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
    .name = #call, \
    .id = proto, \
    .system = __stringify(TRACE_SYSTEM), \
    - .raw_init = ftrace_raw_init_event_##call, \
    + .raw_init = ftrace_raw_init_event, \
    .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); \
    - init_preds(&event_##call); \
    - return 0; \
    -} \
    +};

    #undef TRACE_EVENT_FORMAT_NOFILTER
    #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, \
    @@ -182,9 +182,8 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
    #undef TRACE_EVENT_FORMAT
    #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
    int \
    -ftrace_define_fields_##call(void) \
    +ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
    { \
    - struct ftrace_event_call *event_call = &event_##call; \
    struct args field; \
    int ret; \
    \

    --
    Masami Hiramatsu

    Software Engineer
    Hitachi Computer Products (America), Inc.
    Software Solutions Division

    e-mail: mhiramat@redhat.com


    \
     
     \ /
      Last update: 2009-07-16 18:01    [from the cache]
    ©2003-2011 Jasper Spaans