Introduce the new macro TRACEPOINT_STRUCT to define ctf struct metadata
that can be used by tracepoints using _struct as entry and tp_memcpy_struct
to copy a struct field.
Struct metadata can contain nested structs.
This extra metadata is added to the metadata file only if events use it.

Signed-off-by: Geneviève Bastien <[email protected]>
---
 lttng-events.c              | 166 ++++++++++++++++++++++++++++++++++-
 lttng-events.h              |  44 ++++++++++
 probes/lttng-events-reset.h |  15 ++++
 probes/lttng-events.h       | 206 ++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 421 insertions(+), 10 deletions(-)

diff --git a/lttng-events.c b/lttng-events.c
index 4f30904..b332c29 100644
--- a/lttng-events.c
+++ b/lttng-events.c
@@ -61,6 +61,7 @@ void synchronize_trace(void)
 struct lttng_session *lttng_session_create(void)
 {
        struct lttng_session *session;
+       int i;
 
        mutex_lock(&sessions_mutex);
        session = kzalloc(sizeof(struct lttng_session), GFP_KERNEL);
@@ -70,6 +71,11 @@ struct lttng_session *lttng_session_create(void)
        INIT_LIST_HEAD(&session->events);
        uuid_le_gen(&session->uuid);
        list_add(&session->list, &sessions);
+       /* Initialize dumped metadata */
+       for (i = 0; i < NR_METADATA_TYPES; i++) {
+               session->dumped_metadata[i].nr_metadata = 0;
+               session->dumped_metadata[i].next = 0;
+       }
        mutex_unlock(&sessions_mutex);
        return session;
 }
@@ -78,7 +84,8 @@ void lttng_session_destroy(struct lttng_session *session)
 {
        struct lttng_channel *chan, *tmpchan;
        struct lttng_event *event, *tmpevent;
-       int ret;
+       struct lttng_metadata_dumped_data *dumped;
+       int ret, i, j;
 
        mutex_lock(&sessions_mutex);
        ACCESS_ONCE(session->active) = 0;
@@ -96,6 +103,15 @@ void lttng_session_destroy(struct lttng_session *session)
        list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
                _lttng_channel_destroy(chan);
        list_del(&session->list);
+       /* Destroy dumped metadata */
+       for (i = 0; i < NR_METADATA_TYPES; i++) {
+               dumped = session->dumped_metadata[i].next;
+               for (j = 0; j < session->dumped_metadata[i].nr_metadata; j++) {
+                       dumped = dumped->next;
+                       kfree(dumped);
+               }
+
+       }
        mutex_unlock(&sessions_mutex);
        kfree(session);
 }
@@ -654,6 +670,13 @@ int _lttng_field_statedump(struct lttng_session *session,
                                " { encoding = ASCII; }" : "",
                        field->name);
                break;
+       case atype_struct:
+               ret = lttng_metadata_printf(session,
+                       "               struct %s_%s _%s;\n",
+                       field->type.u.ctf_struct.provider,
+                       field->type.u.ctf_struct.name,
+                       field->name);
+               break;
        default:
                WARN_ON_ONCE(1);
                return -EINVAL;
@@ -662,6 +685,141 @@ int _lttng_field_statedump(struct lttng_session *session,
 }
 
 static
+int _lttng_is_type_metadata_dumped(struct lttng_session *session,
+               const struct lttng_metadata *metadata)
+{
+       /* Is the metadata dumped yet ? */
+       struct lttng_metadata_dumped_data *dumped;
+       int is_dumped = 0, i;
+
+       dumped = session->dumped_metadata[metadata->mtype].next;
+       switch (metadata->mtype) {
+       case mtype_struct:
+               for (i = 0; i < 
session->dumped_metadata[metadata->mtype].nr_metadata; i++) {
+                       if (metadata->m.ctf_st.struct_desc ==
+                                       dumped->dumped_ptr.struct_desc) {
+                               is_dumped = 1;
+                               break;
+                       }
+                       dumped = dumped->next;
+               }
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+       return is_dumped;
+}
+
+static int _lttng_type_metadata_mark_dumped(struct lttng_session *session,
+               const struct lttng_metadata *metadata)
+{
+       /* mark this metadata as dumped */
+       struct lttng_metadata_dumped_data *dumped;
+
+       dumped = kzalloc(sizeof(struct lttng_metadata_dumped_data),
+                       GFP_KERNEL);
+       if (!dumped)
+               return -ENOMEM;
+
+       switch (metadata->mtype) {
+       case mtype_struct:
+               dumped->dumped_ptr.struct_desc = metadata->m.ctf_st.struct_desc;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+
+       dumped->next = session->dumped_metadata[metadata->mtype].next;
+       session->dumped_metadata[metadata->mtype].next = dumped;
+       session->dumped_metadata[metadata->mtype].nr_metadata++;
+       return 0;
+}
+
+static
+int _lttng_type_metadata_statedump(struct lttng_session *session,
+       const struct lttng_metadata *metadata, unsigned int nr_metadata);
+
+static
+int _lttng_type_metadata_do_statedump(struct lttng_session *session,
+                       const struct lttng_metadata *meta)
+{
+       int i, ret = 0;
+
+       switch (meta->mtype) {
+       case mtype_struct:
+               ret = _lttng_type_metadata_statedump(session,
+                               meta->m.ctf_st.type_metadata,
+                               meta->m.ctf_st.nr_metadata);
+               if (ret)
+                       return ret;
+
+               ret = lttng_metadata_printf(session,
+                       "struct %s_%s {\n",
+                       meta->m.ctf_st.struct_desc->provider,
+                       meta->m.ctf_st.struct_desc->name
+               );
+               if (ret)
+                       return ret;
+
+               /* Print fields */
+               for (i = 0; i < meta->m.ctf_st.struct_desc->nr_fields; i++) {
+                       const struct lttng_event_field *field;
+
+                       field = &meta->m.ctf_st.struct_desc->fields[i];
+                       ret = _lttng_field_statedump(session, field);
+                       if (ret)
+                               return ret;
+               }
+               ret = lttng_metadata_printf(session,
+                               "};\n\n");
+               if (ret)
+                       return ret;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+       if (ret)
+               return ret;
+
+       ret = _lttng_type_metadata_mark_dumped(session, meta);
+       return ret;
+}
+
+static
+int _lttng_type_metadata_statedump(struct lttng_session *session,
+       const struct lttng_metadata *metadata, unsigned int nr_metadata)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < nr_metadata; i++) {
+               const struct lttng_metadata *meta = &metadata[i];
+
+               if (_lttng_is_type_metadata_dumped(session, meta))
+                       continue;
+
+               ret = _lttng_type_metadata_do_statedump(session, meta);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static
+int _lttng_event_type_metadata_statedump(struct lttng_session *session,
+                        struct lttng_event *event)
+{
+       int ret = 0;
+       const struct lttng_event_desc *desc = event->desc;
+
+       ret = _lttng_type_metadata_statedump(session,
+                       desc->type_metadata, desc->nr_metadata);
+       return ret;
+}
+
+static
 int _lttng_context_metadata_statedump(struct lttng_session *session,
                                    struct lttng_ctx *ctx)
 {
@@ -710,6 +868,11 @@ int _lttng_event_metadata_statedump(struct lttng_session 
*session,
        if (chan == session->metadata)
                return 0;
 
+       /* Dump the type metadata for this event */
+       ret = _lttng_event_type_metadata_statedump(session, event);
+       if (ret)
+               goto end;
+
        ret = lttng_metadata_printf(session,
                "event {\n"
                "       name = %s;\n"
@@ -746,7 +909,6 @@ int _lttng_event_metadata_statedump(struct lttng_session 
*session,
        ret = _lttng_fields_metadata_statedump(session, event);
        if (ret)
                goto end;
-
        /*
         * LTTng space reservation can only reserve multiples of the
         * byte size.
diff --git a/lttng-events.h b/lttng-events.h
index 37a5db7..67c49f1 100644
--- a/lttng-events.h
+++ b/lttng-events.h
@@ -47,9 +47,16 @@ enum abstract_types {
        atype_array,
        atype_sequence,
        atype_string,
+       atype_struct,
        NR_ABSTRACT_TYPES,
 };
 
+/* Metadata types */
+enum metadata_types {
+       mtype_struct,
+       NR_METADATA_TYPES,
+};
+
 /* Update the string_encodings name table in lttng-types.c along with this 
enum */
 enum lttng_string_encodings {
        lttng_encode_none = 0,
@@ -115,6 +122,9 @@ struct lttng_type {
                        struct lttng_basic_type length_type;
                        struct lttng_basic_type elem_type;
                } sequence;
+               struct {
+                       const char *name, *provider;
+               } ctf_struct;
        } u;
 };
 
@@ -161,12 +171,45 @@ struct lttng_ctx {
        unsigned int allocated_fields;
 };
 
+struct lttng_struct_desc {
+       const char *provider, *name;
+       const struct lttng_event_field *fields; /* fields */
+       unsigned int nr_fields;
+       struct module *owner;
+};
+
+struct lttng_metadata {
+       enum metadata_types mtype;
+       union {
+               struct {
+                       const struct lttng_struct_desc *struct_desc;
+                       const struct lttng_metadata *type_metadata;
+                       unsigned int nr_metadata;
+               } ctf_st;
+       } m;
+};
+
+struct lttng_metadata_dumped_data {
+       union {
+               const struct lttng_struct_desc *struct_desc;
+       } dumped_ptr;
+       struct lttng_metadata_dumped_data *next;
+};
+
+struct lttng_metadata_dumped {
+       unsigned int nr_metadata;
+       struct lttng_metadata_dumped_data *next;
+};
+
 struct lttng_event_desc {
        const char *name;
        void *probe_callback;
        const struct lttng_event_ctx *ctx;      /* context */
        const struct lttng_event_field *fields; /* event payload */
+       /* type metadata added by events */
+       const struct lttng_metadata *type_metadata;
        unsigned int nr_fields;
+       unsigned int nr_metadata;
        struct module *owner;
 };
 
@@ -277,6 +320,7 @@ struct lttng_session {
        struct list_head list;          /* Session list */
        unsigned int free_chan_id;      /* Next chan ID to allocate */
        uuid_le uuid;                   /* Trace session unique ID */
+       struct lttng_metadata_dumped dumped_metadata[NR_METADATA_TYPES];
        unsigned int metadata_dumped:1;
 };
 
diff --git a/probes/lttng-events-reset.h b/probes/lttng-events-reset.h
index 44e8ba5..dd60ca6 100644
--- a/probes/lttng-events-reset.h
+++ b/probes/lttng-events-reset.h
@@ -20,6 +20,9 @@
 
 /* Reset macros used within TRACE_EVENT to "nothing" */
 
+#undef TRACE_METADATA
+#define TRACE_METADATA 1
+
 #undef __field_full
 #define __field_full(_type, _item, _order, _base)
 
@@ -35,6 +38,9 @@
 #undef __string
 #define __string(_item, _src)
 
+#undef __struct
+#define __struct(_provider, _type, _item, _params)
+
 #undef tp_assign
 #define tp_assign(dest, src)
 
@@ -47,6 +53,9 @@
 #undef tp_strcpy
 #define tp_strcpy(dest, src)
 
+#undef tp_memcpy_struct
+#define tp_memcpy_struct(provider, name, dest, src)
+
 #undef __get_str
 #define __get_str(field)
 
@@ -65,6 +74,9 @@
 #undef TP_STRUCT__entry
 #define TP_STRUCT__entry(args...)
 
+#undef TP_FIELDS
+#define TP_FIELDS(args...)
+
 #undef TP_fast_assign
 #define TP_fast_assign(args...)
 
@@ -94,3 +106,6 @@
 
 #undef TRACE_EVENT_FLAGS
 #define TRACE_EVENT_FLAGS(name, value)
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)
diff --git a/probes/lttng-events.h b/probes/lttng-events.h
index 8a3a886..93f4abc 100644
--- a/probes/lttng-events.h
+++ b/probes/lttng-events.h
@@ -263,9 +263,31 @@ void trace_##_name(void *__data);
 #define __string_from_user(_item, _src)                                \
        __string(_item, _src)
 
+#undef __struct
+#define __struct(_provider, _type, _item, _params)             \
+       {                                                       \
+         .name = #_item,                                       \
+         .type =                                               \
+         {                                                     \
+               .atype = atype_struct,                          \
+               .u.ctf_struct.provider = #_provider,            \
+               .u.ctf_struct.name = #_type,                    \
+         },                                                    \
+       },
+
 #undef TP_STRUCT__entry
 #define TP_STRUCT__entry(args...) args /* Only one used in this phase */
 
+#undef TP_FIELDS
+#define TP_FIELDS(args...) args        /* Only one used in this phase */
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)    \
+       static const struct lttng_event_field                   \
+               __struct_fields___##_provider##_##_name[] = {   \
+                       _fields                                 \
+       };
+
 #undef DECLARE_EVENT_CLASS_NOARGS
 #define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \
        static const struct lttng_event_field __event_fields___##_name[] = { \
@@ -301,6 +323,74 @@ static void __event_probe__##_name(void *__data);
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 /*
+ * Stage 3.2 of the trace events.
+ *
+ * Create type metadata description
+ */
+
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT 
*/
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)    \
+static struct lttng_struct_desc __struct_desc___##_provider##_##_name = {\
+               .fields = __struct_fields___##_provider##_##_name,      \
+               .nr_fields = 
ARRAY_SIZE(__struct_fields___##_provider##_##_name),\
+               .provider = #_provider,                                 \
+               .name = #_name,                                         \
+               .owner = THIS_MODULE,                                   \
+       };
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Stage 3.3 of the trace events.
+ *
+ * Associate metadata description to event or event template or other struct
+ */
+
+/* Named field types must be defined in lttng-types.h */
+
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT 
*/
+
+#undef __struct
+#define __struct(_provider, _type, _item, _params)                     \
+       {                                                               \
+               .mtype = mtype_struct,                                  \
+               .m.ctf_st.struct_desc = &__struct_desc___##_provider##_##_type,\
+               .m.ctf_st.type_metadata = 
__type_metadata_for__##_provider##_##_type,\
+               .m.ctf_st.nr_metadata = 
ARRAY_SIZE(__type_metadata_for__##_provider##_##_type),\
+       },
+
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args /* Only one used in this phase */
+
+#undef TP_FIELDS
+#define TP_FIELDS(args...) args
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)    \
+static const struct lttng_metadata 
__type_metadata_for__##_provider##_##_name[] = {\
+       _fields                                                         \
+};
+
+
+
+#undef DECLARE_EVENT_CLASS_NOARGS
+#define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \
+static const struct lttng_metadata __type_metadata_for__##_name[] = {  \
+       _tstruct                \
+};
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \
+       DECLARE_EVENT_CLASS_NOARGS(_name, PARAMS(_tstruct), PARAMS(_assign), \
+                       PARAMS(_print))
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+
+/*
  * Stage 3.9 of the trace events.
  *
  * Create event descriptions.
@@ -318,9 +408,11 @@ static void __event_probe__##_name(void *__data);
 #define DEFINE_EVENT_MAP_NOARGS(_template, _name, _map)                        
\
 static const struct lttng_event_desc __event_desc___##_map = {         \
        .fields = __event_fields___##_template,                         \
+       .type_metadata = __type_metadata_for__##_template,              \
        .name = #_map,                                                  \
        .probe_callback = (void *) TP_PROBE_CB(_template),              \
        .nr_fields = ARRAY_SIZE(__event_fields___##_template),          \
+       .nr_metadata = ARRAY_SIZE(__type_metadata_for__##_template),    \
        .owner = THIS_MODULE,                                           \
 };
 
@@ -379,9 +471,12 @@ static __used struct lttng_probe_desc 
TP_ID(__probe_desc___, TRACE_SYSTEM) = {
 #undef TP_ID
 
 /*
- * Stage 6 of the trace events.
+ * Stage 6.0 of the trace events.
  *
  * Create static inline function that calculates event size.
+ *
+ * First stage creates function to calculate sizes of sub-metadata
+ * (with no effect on the dynamic length values)
  */
 
 #include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT 
*/
@@ -403,6 +498,57 @@ static __used struct lttng_probe_desc 
TP_ID(__probe_desc___, TRACE_SYSTEM) = {
        __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(u32));  
 \
        __event_len += sizeof(u32);                                            \
        __event_len += lib_ring_buffer_align(__event_len, 
lttng_alignof(_type)); \
+       __event_len += sizeof(_type) * (_length);                              \
+
+#undef __string
+#define __string(_item, _src)                                                 \
+       __event_len += strlen(_src) + 1;
+
+/*
+ * strlen_user includes \0. If returns 0, it faulted, so we set size to
+ * 1 (\0 only).
+ */
+#undef __string_from_user
+#define __string_from_user(_item, _src)                                        
       \
+       __event_len += max_t(size_t, lttng_strlen_user_inatomic(_src), 1);
+
+#undef __struct
+#define __struct(_provider, _type, _item, _params)                     \
+       __event_len += __struct_get_size__##_provider##_##_type(_params);\
+
+#undef TP_PROTO
+#define TP_PROTO(args...) args
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef TP_FIELDS
+#define TP_FIELDS(args...) args
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)    \
+static inline size_t __struct_get_size__##_provider##_##_name(_proto)   \
+       {                                                               \
+       size_t __event_len = 0;                                         \
+                                                                       \
+       _fields                                                         \
+       return __event_len;                                             \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+/*
+ * Stage 6.1 of the trace events.
+ *
+ * Create static inline function that calculates event size, this time adding
+ * the size to the dynamic_len array
+ */
+
+#undef __dynamic_array_enc_ext
+#define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, 
_encoding)\
+       __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(u32)); \
+       __event_len += sizeof(u32);                                            \
+       __event_len += lib_ring_buffer_align(__event_len, 
lttng_alignof(_type));\
        __dynamic_len[__dynamic_len_idx] = (_length);                          \
        __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx];       \
        __dynamic_len_idx++;
@@ -420,11 +566,13 @@ static __used struct lttng_probe_desc 
TP_ID(__probe_desc___, TRACE_SYSTEM) = {
        __event_len += __dynamic_len[__dynamic_len_idx++] =                    \
                max_t(size_t, lttng_strlen_user_inatomic(_src), 1);
 
-#undef TP_PROTO
-#define TP_PROTO(args...) args
+#undef __struct
+#define __struct(_provider, _type, _item, _params)                     \
+       __event_len += __dynamic_len[__dynamic_len_idx++] =             \
+               __struct_get_size__##_provider##_##_type(_params);
 
-#undef TP_STRUCT__entry
-#define TP_STRUCT__entry(args...) args
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)
 
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
@@ -470,12 +618,36 @@ static inline size_t __event_get_size__##_name(size_t 
*__dynamic_len, _proto) \
 #undef __string_from_user
 #define __string_from_user(_item, _src)
 
+#undef __struct
+#define __struct(_provider, _type, _item, _params)                     \
+       __event_align = max_t(size_t, __event_align,                    \
+               __instruct_get_align__##_provider##_##_type(_params));
+
 #undef TP_PROTO
 #define TP_PROTO(args...) args
 
+#undef TP_ARGS
+#define TP_ARGS(args...) args
+
 #undef TP_STRUCT__entry
 #define TP_STRUCT__entry(args...) args
 
+#undef TP_FIELDS
+#define TP_FIELDS(args...) args
+
+#undef TRACEPOINT_STRUCT
+#define TRACEPOINT_STRUCT(_provider, _name, _proto, _args, _fields)    \
+static inline size_t __struct_get_align__##_provider##_##_name(_proto) \
+{                                                                      \
+       size_t __event_align = 1;                                       \
+       _fields                                                         \
+       return __event_align;                                           \
+}                                                                      \
+static inline size_t __instruct_get_align__##_provider##_##_name(_proto)\
+{                                                                      \
+       return __struct_get_align__##_provider##_##_name(_args);        \
+}
+
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
 static inline size_t __event_get_align__##_name(_proto)                        
      \
@@ -487,7 +659,6 @@ static inline size_t __event_get_align__##_name(_proto)     
                      \
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
-
 /*
  * Stage 8 of the trace events.
  *
@@ -517,6 +688,9 @@ static inline size_t __event_get_align__##_name(_proto)     
                      \
 #define __string_from_user(_item, _src)                \
        __string(_item, _src)
 
+#undef __struct
+#define __struct(_provider, _type, _item, _params)     char _item;
+
 #undef TP_STRUCT__entry
 #define TP_STRUCT__entry(args...) args
 
@@ -528,7 +702,6 @@ struct __event_typemap__##_name {                           
              \
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
-
 /*
  * Stage 9 of the trace events.
  *
@@ -568,6 +741,11 @@ __end_field_##_item:
 #define __string_from_user(_item, _src)                                        
\
        __string(_item, _src)
 
+#undef __struct
+#define __struct(_provider, _type, _item, _params)                     \
+       goto __assign_##_item;                                          \
+__end_field_##_item:
+
 /*
  * Macros mapping tp_assign() to "=", tp_memcpy() to memcpy() and tp_strcpy() 
to
  * strcpy().
@@ -624,12 +802,24 @@ __assign_##dest##_2:                                      
                \
 #define tp_memcpy_dyn_from_user(dest, src)                             \
        tp_memcpy_dyn_gen(event_write_from_user, dest, src)
 
+#undef tp_memcpy_struct_gen
+#define tp_memcpy_struct_gen(write_ops, provider, name, dest, src)     \
+__assign_##dest:                                                       \
+       lib_ring_buffer_align_ctx(&__ctx, 
__struct_get_align__##provider##_##name(src));\
+       __chan->ops->write_ops(&__ctx, src,                             \
+               sizeof(__typemap.dest) * __get_dynamic_array_len(dest));\
+       goto __end_field_##dest;
+
+#undef tp_memcpy_struct
+#define tp_memcpy_struct(provider, name, dest, src)    \
+               tp_memcpy_struct_gen(event_write, provider, name, dest, src)
+
 /*
  * The string length including the final \0.
  */
 #undef tp_copy_string_from_user
 #define tp_copy_string_from_user(dest, src)                            \
-       __assign_##dest:                                                \
+__assign_##dest:                                                       \
        {                                                               \
                size_t __ustrlen;                                       \
                                                                        \
-- 
1.8.2.1


_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to