On Tue, Jun 30, 2009 at 09:09:17PM -0400, Masami Hiramatsu wrote:
> 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.
> 
> Signed-off-by: Masami Hiramatsu <mhira...@redhat.com>
> Cc: Steven Rostedt <rost...@goodmis.org>
> Cc: Ingo Molnar <mi...@elte.hu>
> Cc: Tom Zanussi <tzanu...@gmail.com>
> Cc: Frederic Weisbecker <fweis...@gmail.com>



Looks good too.

Acked-by: Frederic Weisbecker <fweis...@gmail.com>



> ---
> 
>  include/linux/ftrace_event.h |   13 +++++---
>  include/trace/ftrace.h       |   22 +++++++------
>  kernel/trace/trace_events.c  |   70 
> ++++++++++++++++++++++++++++++++----------
>  kernel/trace/trace_export.c  |   27 ++++++++--------
>  4 files changed, 85 insertions(+), 47 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 53c8fd3..94ff41e 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -60,9 +60,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;
>  
> @@ -74,8 +72,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)
>  {
> @@ -84,14 +80,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;
>       }
> @@ -574,7 +570,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!!
> @@ -921,7 +917,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);
> @@ -945,7 +941,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);
> @@ -965,6 +961,52 @@ 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 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;         \
> @@ -1070,13 +1112,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);
> +                     __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: mhira...@redhat.com

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to