Support for linux kernels 2.6.32 through 2.6.37
[lttng-modules.git] / linux-patches / backport-tracepoint-data-2.6.32-33.patch
diff --git a/linux-patches/backport-tracepoint-data-2.6.32-33.patch b/linux-patches/backport-tracepoint-data-2.6.32-33.patch
new file mode 100644 (file)
index 0000000..e344bac
--- /dev/null
@@ -0,0 +1,541 @@
+commit 2c2a566b64b4254c530fb0c2222b30e8a739bac9
+Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Date:   Sat Sep 1 17:45:09 2012 -0700
+
+    tracing: Let tracepoints have data passed to tracepoint callbacks (backport)
+    
+    Backport of commit 38516ab59fbc5b3bb278cf5e1fe2867c70cff32e for
+    2.6.32.x and 2.6.33.x. Keeping kABI compatibility.
+    
+    Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+
+---
+ include/linux/tracepoint.h |  141 ++++++++++++++++++++++++++++++++++----------
+ kernel/tracepoint.c        |  144 ++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 215 insertions(+), 70 deletions(-)
+
+Index: linux/include/linux/tracepoint.h
+===================================================================
+--- linux.orig/include/linux/tracepoint.h
++++ linux/include/linux/tracepoint.h
+@@ -20,12 +20,20 @@
+ struct module;
+ struct tracepoint;
++#define HAVE_KABI_2635_TRACEPOINT
++
++struct tracepoint_func {
++      void *func;
++      void *data;
++      bool kabi_2635;
++};
++
+ struct tracepoint {
+       const char *name;               /* Tracepoint name */
+       int state;                      /* State. */
+       void (*regfunc)(void);
+       void (*unregfunc)(void);
+-      void **funcs;
++      struct tracepoint_func *funcs;
+ } __attribute__((aligned(32)));               /*
+                                        * Aligned on 32 bytes because it is
+                                        * globally visible and gcc happily
+@@ -43,17 +51,33 @@ struct tracepoint {
+ /*
+  * it_func[0] is never NULL because there is at least one element in the array
+  * when the array itself is non NULL.
++ *
++ * Note, the proto and args passed in includes "__data" as the first parameter.
++ * The reason for this is to handle the "void" prototype. If a tracepoint
++ * has a "void" prototype, then it is invalid to declare a function
++ * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
++ * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
+  */
+-#define __DO_TRACE(tp, proto, args)                                   \
++#define __DO_TRACE(tp, data_proto, data_args, proto, args)            \
+       do {                                                            \
+-              void **it_func;                                         \
++              struct tracepoint_func *it_func_ptr;                    \
++              void *it_func;                                          \
+                                                                       \
+               rcu_read_lock_sched_notrace();                          \
+-              it_func = rcu_dereference((tp)->funcs);                 \
+-              if (it_func) {                                          \
++              it_func_ptr = rcu_dereference((tp)->funcs);             \
++              if (it_func_ptr) {                                      \
+                       do {                                            \
+-                              ((void(*)(proto))(*it_func))(args);     \
+-                      } while (*(++it_func));                         \
++                              if (it_func_ptr->kabi_2635) {           \
++                                      void *__data;                   \
++                                                                      \
++                                      it_func = (it_func_ptr)->func;  \
++                                      __data = (it_func_ptr)->data;   \
++                                      ((void(*)(data_proto))(it_func))(data_args); \
++                              } else {                                \
++                                      it_func = (it_func_ptr)->func;  \
++                                      ((void(*)(proto))(it_func))(args); \
++                              }                                       \
++                      } while ((++it_func_ptr)->func);                \
+               }                                                       \
+               rcu_read_unlock_sched_notrace();                        \
+       } while (0)
+@@ -63,22 +87,39 @@ struct tracepoint {
+  * not add unwanted padding between the beginning of the section and the
+  * structure. Force alignment to the same alignment as the section start.
+  */
+-#define DECLARE_TRACE(name, proto, args)                              \
++#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)     \
+       extern struct tracepoint __tracepoint_##name;                   \
+       static inline void trace_##name(proto)                          \
+       {                                                               \
+               if (unlikely(__tracepoint_##name.state))                \
+                       __DO_TRACE(&__tracepoint_##name,                \
+-                              TP_PROTO(proto), TP_ARGS(args));        \
++                              TP_PROTO(data_proto),                   \
++                              TP_ARGS(data_args),                     \
++                              TP_PROTO(proto),                        \
++                              TP_ARGS(args));                         \
+       }                                                               \
+-      static inline int register_trace_##name(void (*probe)(proto))   \
+-      {                                                               \
++      static inline int                                               \
++      register_trace_##name(void (*probe)(proto))                     \
++      {                                                               \
+               return tracepoint_probe_register(#name, (void *)probe); \
+-      }                                                               \
+-      static inline int unregister_trace_##name(void (*probe)(proto)) \
+-      {                                                               \
+-              return tracepoint_probe_unregister(#name, (void *)probe);\
+-      }
++      }                                                               \
++      static inline int                                               \
++      unregister_trace_##name(void (*probe)(proto))                   \
++      {                                                               \
++              return tracepoint_probe_unregister(#name, (void *)probe); \
++      }                                                               \
++      static inline int                                               \
++      kabi_2635_register_trace_##name(void (*probe)(data_proto), void *data) \
++      {                                                               \
++              return kabi_2635_tracepoint_probe_register(#name, (void *)probe,        \
++                                               data);                 \
++      }                                                               \
++      static inline int                                               \
++      kabi_2635_unregister_trace_##name(void (*probe)(data_proto), void *data) \
++      {                                                               \
++              return kabi_2635_tracepoint_probe_unregister(#name, (void *)probe, \
++                                                 data);               \
++      }
+ #define DEFINE_TRACE_FN(name, reg, unreg)                             \
+@@ -100,19 +141,29 @@ extern void tracepoint_update_probe_rang
+       struct tracepoint *end);
+ #else /* !CONFIG_TRACEPOINTS */
+-#define DECLARE_TRACE(name, proto, args)                              \
+-      static inline void _do_trace_##name(struct tracepoint *tp, proto) \
+-      { }                                                             \
+-      static inline void trace_##name(proto)                          \
+-      { }                                                             \
+-      static inline int register_trace_##name(void (*probe)(proto))   \
+-      {                                                               \
+-              return -ENOSYS;                                         \
+-      }                                                               \
+-      static inline int unregister_trace_##name(void (*probe)(proto)) \
+-      {                                                               \
+-              return -ENOSYS;                                         \
+-      }
++#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)     \
++      static inline void trace_##name(proto)                          \
++      { }                                                             \
++      static inline int                                               \
++      register_trace_##name(void (*probe)(proto))                     \
++      {                                                               \
++              return -ENOSYS;                                         \
++      }                                                               \
++      static inline int                                               \
++      unregister_trace_##name(void (*probe)(proto))                   \
++      {                                                               \
++              return -ENOSYS;                                         \
++      }                                                               \
++      static inline int                                               \
++      kabi_2635_register_trace_##name(void (*probe)(data_proto), void *data) \
++      {                                                               \
++              return -ENOSYS;                                         \
++      }                                                               \
++      static inline int                                               \
++      kabi_2635_unregister_trace_##name(void (*probe)(data_proto), void *data) \
++      {                                                               \
++              return -ENOSYS;                                         \
++      }
+ #define DEFINE_TRACE_FN(name, reg, unreg)
+ #define DEFINE_TRACE(name)
+@@ -123,6 +174,28 @@ static inline void tracepoint_update_pro
+       struct tracepoint *end)
+ { }
+ #endif /* CONFIG_TRACEPOINTS */
++
++/*
++ * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype
++ * (void). "void" is a special value in a function prototype and can
++ * not be combined with other arguments. Since the DECLARE_TRACE()
++ * macro adds a data element at the beginning of the prototype,
++ * we need a way to differentiate "(void *data, proto)" from
++ * "(void *data, void)". The second prototype is invalid.
++ *
++ * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype
++ * and "void *__data" as the callback prototype.
++ *
++ * DECLARE_TRACE() passes "proto" as the tracepoint protoype and
++ * "void *__data, proto" as the callback prototype.
++ */
++#define DECLARE_TRACE_NOARGS(name)                                    \
++      __DECLARE_TRACE(name, void, , void *__data, __data)
++#define DECLARE_TRACE(name, proto, args)                              \
++      __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
++                      PARAMS(void *__data, proto),                    \
++                      PARAMS(__data, args))
++
+ #endif /* DECLARE_TRACE */
+ /*
+@@ -130,15 +203,23 @@ static inline void tracepoint_update_pro
+  * Internal API, should not be used directly.
+  */
+ extern int tracepoint_probe_register(const char *name, void *probe);
++extern int kabi_2635_tracepoint_probe_register(const char *name, void *probe, void *data);
+ /*
+  * Disconnect a probe from a tracepoint.
+  * Internal API, should not be used directly.
+  */
+-extern int tracepoint_probe_unregister(const char *name, void *probe);
++extern int
++tracepoint_probe_unregister(const char *name, void *probe);
++extern int
++kabi_2635_tracepoint_probe_unregister(const char *name, void *probe, void *data);
+ extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
++extern int kabi_2635_tracepoint_probe_register_noupdate(const char *name, void *probe,
++                                            void *data);
+ extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
++extern int kabi_2635_tracepoint_probe_unregister_noupdate(const char *name, void *probe,
++                                              void *data);
+ extern void tracepoint_probe_update_all(void);
+ struct tracepoint_iter {
+Index: linux/kernel/tracepoint.c
+===================================================================
+--- linux.orig/kernel/tracepoint.c
++++ linux/kernel/tracepoint.c
+@@ -54,7 +54,7 @@ static struct hlist_head tracepoint_tabl
+  */
+ struct tracepoint_entry {
+       struct hlist_node hlist;
+-      void **funcs;
++      struct tracepoint_func *funcs;
+       int refcount;   /* Number of times armed. 0 if disarmed. */
+       char name[0];
+ };
+@@ -64,12 +64,12 @@ struct tp_probes {
+               struct rcu_head rcu;
+               struct list_head list;
+       } u;
+-      void *probes[0];
++      struct tracepoint_func probes[0];
+ };
+ static inline void *allocate_probes(int count)
+ {
+-      struct tp_probes *p  = kmalloc(count * sizeof(void *)
++      struct tp_probes *p  = kmalloc(count * sizeof(struct tracepoint_func)
+                       + sizeof(struct tp_probes), GFP_KERNEL);
+       return p == NULL ? NULL : p->probes;
+ }
+@@ -79,7 +79,7 @@ static void rcu_free_old_probes(struct r
+       kfree(container_of(head, struct tp_probes, u.rcu));
+ }
+-static inline void release_probes(void *old)
++static inline void release_probes(struct tracepoint_func *old)
+ {
+       if (old) {
+               struct tp_probes *tp_probes = container_of(old,
+@@ -95,15 +95,16 @@ static void debug_print_probes(struct tr
+       if (!tracepoint_debug || !entry->funcs)
+               return;
+-      for (i = 0; entry->funcs[i]; i++)
+-              printk(KERN_DEBUG "Probe %d : %p\n", i, entry->funcs[i]);
++      for (i = 0; entry->funcs[i].func; i++)
++              printk(KERN_DEBUG "Probe %d : %p\n", i, entry->funcs[i].func);
+ }
+-static void *
+-tracepoint_entry_add_probe(struct tracepoint_entry *entry, void *probe)
++static struct tracepoint_func *
++tracepoint_entry_add_probe(struct tracepoint_entry *entry,
++                         void *probe, void *data, bool kabi_2635)
+ {
+       int nr_probes = 0;
+-      void **old, **new;
++      struct tracepoint_func *old, *new;
+       WARN_ON(!probe);
+@@ -111,8 +112,9 @@ tracepoint_entry_add_probe(struct tracep
+       old = entry->funcs;
+       if (old) {
+               /* (N -> N+1), (N != 0, 1) probes */
+-              for (nr_probes = 0; old[nr_probes]; nr_probes++)
+-                      if (old[nr_probes] == probe)
++              for (nr_probes = 0; old[nr_probes].func; nr_probes++)
++                      if (old[nr_probes].func == probe &&
++                          old[nr_probes].data == data)
+                               return ERR_PTR(-EEXIST);
+       }
+       /* + 2 : one for new probe, one for NULL func */
+@@ -120,9 +122,11 @@ tracepoint_entry_add_probe(struct tracep
+       if (new == NULL)
+               return ERR_PTR(-ENOMEM);
+       if (old)
+-              memcpy(new, old, nr_probes * sizeof(void *));
+-      new[nr_probes] = probe;
+-      new[nr_probes + 1] = NULL;
++              memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
++      new[nr_probes].func = probe;
++      new[nr_probes].data = data;
++      new[nr_probes].kabi_2635 = kabi_2635;
++      new[nr_probes + 1].func = NULL;
+       entry->refcount = nr_probes + 1;
+       entry->funcs = new;
+       debug_print_probes(entry);
+@@ -130,10 +134,11 @@ tracepoint_entry_add_probe(struct tracep
+ }
+ static void *
+-tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe)
++tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
++                            void *probe, void *data)
+ {
+       int nr_probes = 0, nr_del = 0, i;
+-      void **old, **new;
++      struct tracepoint_func *old, *new;
+       old = entry->funcs;
+@@ -142,8 +147,10 @@ tracepoint_entry_remove_probe(struct tra
+       debug_print_probes(entry);
+       /* (N -> M), (N > 1, M >= 0) probes */
+-      for (nr_probes = 0; old[nr_probes]; nr_probes++) {
+-              if ((!probe || old[nr_probes] == probe))
++      for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
++              if (!probe ||
++                  (old[nr_probes].func == probe &&
++                   old[nr_probes].data == data))
+                       nr_del++;
+       }
+@@ -160,10 +167,11 @@ tracepoint_entry_remove_probe(struct tra
+               new = allocate_probes(nr_probes - nr_del + 1);
+               if (new == NULL)
+                       return ERR_PTR(-ENOMEM);
+-              for (i = 0; old[i]; i++)
+-                      if ((probe && old[i] != probe))
++              for (i = 0; old[i].func; i++)
++                      if (probe &&
++                          (old[i].func != probe || old[i].data != data))
+                               new[j++] = old[i];
+-              new[nr_probes - nr_del] = NULL;
++              new[nr_probes - nr_del].func = NULL;
+               entry->refcount = nr_probes - nr_del;
+               entry->funcs = new;
+       }
+@@ -315,18 +323,19 @@ static void tracepoint_update_probes(voi
+       module_update_tracepoints();
+ }
+-static void *tracepoint_add_probe(const char *name, void *probe)
++static struct tracepoint_func *
++tracepoint_add_probe(const char *name, void *probe, void *data, bool kabi_2635)
+ {
+       struct tracepoint_entry *entry;
+-      void *old;
++      struct tracepoint_func *old;
+       entry = get_tracepoint(name);
+       if (!entry) {
+               entry = add_tracepoint(name);
+               if (IS_ERR(entry))
+-                      return entry;
++                      return (struct tracepoint_func *)entry;
+       }
+-      old = tracepoint_entry_add_probe(entry, probe);
++      old = tracepoint_entry_add_probe(entry, probe, data, kabi_2635);
+       if (IS_ERR(old) && !entry->refcount)
+               remove_tracepoint(entry);
+       return old;
+@@ -340,12 +349,14 @@ static void *tracepoint_add_probe(const
+  * Returns 0 if ok, error value on error.
+  * The probe address must at least be aligned on the architecture pointer size.
+  */
+-int tracepoint_probe_register(const char *name, void *probe)
++static
++int ___tracepoint_probe_register(const char *name, void *probe, void *data,
++                      bool kabi_2635)
+ {
+-      void *old;
++      struct tracepoint_func *old;
+       mutex_lock(&tracepoints_mutex);
+-      old = tracepoint_add_probe(name, probe);
++      old = tracepoint_add_probe(name, probe, data, kabi_2635);
+       mutex_unlock(&tracepoints_mutex);
+       if (IS_ERR(old))
+               return PTR_ERR(old);
+@@ -354,17 +365,30 @@ int tracepoint_probe_register(const char
+       release_probes(old);
+       return 0;
+ }
++
++int kabi_2635_tracepoint_probe_register(const char *name, void *probe, void *data)
++{
++      return ___tracepoint_probe_register(name, probe, data, 1);
++}
++EXPORT_SYMBOL_GPL(kabi_2635_tracepoint_probe_register);
++
++
++int tracepoint_probe_register(const char *name, void *probe)
++{
++      return ___tracepoint_probe_register(name, probe, NULL, 0);
++}
+ EXPORT_SYMBOL_GPL(tracepoint_probe_register);
+-static void *tracepoint_remove_probe(const char *name, void *probe)
++static struct tracepoint_func *
++tracepoint_remove_probe(const char *name, void *probe, void *data)
+ {
+       struct tracepoint_entry *entry;
+-      void *old;
++      struct tracepoint_func *old;
+       entry = get_tracepoint(name);
+       if (!entry)
+               return ERR_PTR(-ENOENT);
+-      old = tracepoint_entry_remove_probe(entry, probe);
++      old = tracepoint_entry_remove_probe(entry, probe, data);
+       if (IS_ERR(old))
+               return old;
+       if (!entry->refcount)
+@@ -382,12 +406,13 @@ static void *tracepoint_remove_probe(con
+  * itself uses stop_machine(), which insures that every preempt disabled section
+  * have finished.
+  */
+-int tracepoint_probe_unregister(const char *name, void *probe)
++static
++int ___tracepoint_probe_unregister(const char *name, void *probe, void *data)
+ {
+-      void *old;
++      struct tracepoint_func *old;
+       mutex_lock(&tracepoints_mutex);
+-      old = tracepoint_remove_probe(name, probe);
++      old = tracepoint_remove_probe(name, probe, data);
+       mutex_unlock(&tracepoints_mutex);
+       if (IS_ERR(old))
+               return PTR_ERR(old);
+@@ -396,6 +421,17 @@ int tracepoint_probe_unregister(const ch
+       release_probes(old);
+       return 0;
+ }
++
++int kabi_2635_tracepoint_probe_unregister(const char *name, void *probe, void *data)
++{
++      return ___tracepoint_probe_unregister(name, probe, data);
++}
++EXPORT_SYMBOL_GPL(kabi_2635_tracepoint_probe_unregister);
++
++int tracepoint_probe_unregister(const char *name, void *probe)
++{
++      return ___tracepoint_probe_unregister(name, probe, NULL);
++}
+ EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
+ static LIST_HEAD(old_probes);
+@@ -418,12 +454,14 @@ static void tracepoint_add_old_probes(vo
+  *
+  * caller must call tracepoint_probe_update_all()
+  */
+-int tracepoint_probe_register_noupdate(const char *name, void *probe)
++static
++int ___tracepoint_probe_register_noupdate(const char *name, void *probe,
++                                     void *data, bool kabi_2635)
+ {
+-      void *old;
++      struct tracepoint_func *old;
+       mutex_lock(&tracepoints_mutex);
+-      old = tracepoint_add_probe(name, probe);
++      old = tracepoint_add_probe(name, probe, data, kabi_2635);
+       if (IS_ERR(old)) {
+               mutex_unlock(&tracepoints_mutex);
+               return PTR_ERR(old);
+@@ -432,6 +470,18 @@ int tracepoint_probe_register_noupdate(c
+       mutex_unlock(&tracepoints_mutex);
+       return 0;
+ }
++
++int kabi_2635_tracepoint_probe_register_noupdate(const char *name, void *probe,
++                                     void *data)
++{
++      return ___tracepoint_probe_register_noupdate(name, probe, data, 1);
++}
++EXPORT_SYMBOL_GPL(kabi_2635_tracepoint_probe_register_noupdate);
++
++int tracepoint_probe_register_noupdate(const char *name, void *probe)
++{
++      return ___tracepoint_probe_register_noupdate(name, probe, NULL, 0);
++}
+ EXPORT_SYMBOL_GPL(tracepoint_probe_register_noupdate);
+ /**
+@@ -441,12 +491,14 @@ EXPORT_SYMBOL_GPL(tracepoint_probe_regis
+  *
+  * caller must call tracepoint_probe_update_all()
+  */
+-int tracepoint_probe_unregister_noupdate(const char *name, void *probe)
++static
++int ___tracepoint_probe_unregister_noupdate(const char *name, void *probe,
++                                       void *data)
+ {
+-      void *old;
++      struct tracepoint_func *old;
+       mutex_lock(&tracepoints_mutex);
+-      old = tracepoint_remove_probe(name, probe);
++      old = tracepoint_remove_probe(name, probe, data);
+       if (IS_ERR(old)) {
+               mutex_unlock(&tracepoints_mutex);
+               return PTR_ERR(old);
+@@ -455,6 +507,18 @@ int tracepoint_probe_unregister_noupdate
+       mutex_unlock(&tracepoints_mutex);
+       return 0;
+ }
++
++int kabi_2635_tracepoint_probe_unregister_noupdate(const char *name, void *probe,
++                                       void *data)
++{
++      return ___tracepoint_probe_unregister_noupdate(name, probe, data);
++}
++EXPORT_SYMBOL_GPL(kabi_2635_tracepoint_probe_unregister_noupdate);
++
++int tracepoint_probe_unregister_noupdate(const char *name, void *probe)
++{
++      return ___tracepoint_probe_unregister_noupdate(name, probe, NULL);
++}
+ EXPORT_SYMBOL_GPL(tracepoint_probe_unregister_noupdate);
+ /**
This page took 0.028847 seconds and 4 git commands to generate.