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. 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 | 134 +++++++++++++++++++++++++++++++++++++++++- lttng-events.h | 35 +++++++++++ probes/lttng-events-reset.h | 15 +++++ probes/lttng-events.h | 138 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 320 insertions(+), 2 deletions(-) diff --git a/lttng-events.c b/lttng-events.c index 4f30904..431a17c 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -654,6 +654,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 +669,122 @@ int _lttng_field_statedump(struct lttng_session *session, } static +int _lttng_is_extra_metadata_dumped(struct lttng_session *session, + const struct lttng_metadata *metadata) { + /* Is the metadata dumped yet ? */ + struct lttng_metadata_dumped *dumped; + int is_dumped = 0; + + dumped = session->extra_metadata[metadata->mtype]; + switch (metadata->mtype) { + case mtype_struct: + while (dumped) { + if (metadata->m.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_extra_metadata_mark_dumped(struct lttng_session *session, + const struct lttng_metadata *metadata) { + /* mark this metadata as dumped */ + struct lttng_metadata_dumped *dumped, *just_dumped; + + just_dumped = kzalloc(sizeof(struct lttng_metadata_dumped), + GFP_KERNEL); + if (!just_dumped) + return -ENOMEM; + + dumped = session->extra_metadata[metadata->mtype]; + + switch (metadata->mtype) { + case mtype_struct: + just_dumped->dumped_ptr.struct_desc = metadata->m.struct_desc; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + + just_dumped->next = session->extra_metadata[mtype_struct]; + session->extra_metadata[mtype_struct] = just_dumped; + return 0; +} + +static +int _lttng_event_extra_metadata_do_statedump(struct lttng_session *session, + const struct lttng_metadata *meta) +{ + int i, ret = 0; + + switch (meta->mtype) { + case mtype_struct: + + ret = lttng_metadata_printf(session, + "struct %s%s {\n", + meta->m.struct_desc->provider, meta->m.struct_desc->name + ); + if (ret) + return ret; + + /* Print fields */ + for (i = 0; i < meta->m.struct_desc->nr_fields; i++) { + const struct lttng_event_field *field; + field = &meta->m.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_extra_metadata_mark_dumped(session, meta); + return ret; +} + +static +int _lttng_event_extra_metadata_statedump(struct lttng_session *session, + struct lttng_event *event) +{ + const struct lttng_event_desc *desc = event->desc; + int i, ret = 0; + + for (i = 0; i < desc->nr_metadata; i++) { + const struct lttng_metadata *meta = &desc->extra_metadata[i]; + + if (!_lttng_is_extra_metadata_dumped(session, meta)) { + ret = _lttng_event_extra_metadata_do_statedump(session, + meta); + if (ret) + return ret; + } + } + return ret; + +} + +static int _lttng_context_metadata_statedump(struct lttng_session *session, struct lttng_ctx *ctx) { @@ -710,6 +833,11 @@ int _lttng_event_metadata_statedump(struct lttng_session *session, if (chan == session->metadata) return 0; + /* Dump the extra metadata for this event */ + ret = _lttng_event_extra_metadata_statedump(session, event); + if (ret) + goto end; + ret = lttng_metadata_printf(session, "event {\n" " name = %s;\n" @@ -905,7 +1033,7 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) unsigned char uuid_s[37], clock_uuid_s[BOOT_ID_LEN]; struct lttng_channel *chan; struct lttng_event *event; - int ret = 0; + int ret = 0, i; if (!ACCESS_ONCE(session->active)) return 0; @@ -1042,6 +1170,10 @@ int _lttng_session_metadata_statedump(struct lttng_session *session) if (ret) goto end; + /* Initialized undumped metadata */ + for (i = 0; i < NR_METADATA_TYPES; i++) + session->extra_metadata[i] = 0; + skip_session: list_for_each_entry(chan, &session->chan, list) { ret = _lttng_channel_metadata_statedump(session, chan); diff --git a/lttng-events.h b/lttng-events.h index 37a5db7..2cab5f3 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,36 @@ struct lttng_ctx { unsigned int allocated_fields; }; +struct lttng_struct_desc { + const char *name, *provider; + const struct lttng_event_field *fields; /* fields */ + unsigned int nr_fields; + struct module *owner; +}; + +struct lttng_metadata { + enum metadata_types mtype; + union { + struct lttng_struct_desc *struct_desc; + } m; +}; + +struct lttng_metadata_dumped { + union { + struct lttng_struct_desc *struct_desc; + } dumped_ptr; + struct lttng_metadata_dumped *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 */ + /* Extra metadata added by events */ + const struct lttng_metadata *extra_metadata; unsigned int nr_fields; + unsigned int nr_metadata; struct module *owner; }; @@ -277,6 +311,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 *extra_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..bf8bbf1 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(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, _fields) diff --git a/probes/lttng-events.h b/probes/lttng-events.h index 8a3a886..8465095 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.name = #_type, \ + .u.ctf_struct.provider = #_provider, \ + }, \ + }, + #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, _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,60 @@ static void __event_probe__##_name(void *__data); #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* + * Stage 3.2 of the trace events. + * + * Create extra metadata description + */ + +#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ + +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _proto, _fields) \ +static struct lttng_struct_desc __struct_desc___##_provider##_name = { \ + .fields = __struct_fields___##_provider##_name, \ + .name = #_name, \ + .provider = #_provider, \ + .nr_fields = ARRAY_SIZE(__struct_fields___##_provider##_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 + */ + +/* 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.struct_desc = &__struct_desc___##_provider##_type, \ + }, + +#undef TP_STRUCT__entry +#define TP_STRUCT__entry(args...) args /* Only one used in this phase */ + +#undef DECLARE_EVENT_CLASS_NOARGS +#define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \ +static const struct lttng_metadata __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 +394,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, \ + .extra_metadata = __metadata_for__##_template, \ .name = #_map, \ .probe_callback = (void *) TP_PROBE_CB(_template), \ .nr_fields = ARRAY_SIZE(__event_fields___##_template), \ + .nr_metadata = ARRAY_SIZE(__metadata_for__##_template), \ .owner = THIS_MODULE, \ }; @@ -420,12 +498,33 @@ 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 __struct +#define __struct(_provider, _type, _item, _params) \ + __event_len += __dynamic_len[__dynamic_len_idx++] = \ + __struct_get_size__##_provider##_type(__dynamic_len, _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, _fields) \ +static inline size_t __struct_get_size__##_provider##_name(size_t *__dynamic_len, _proto)\ + { \ + size_t __event_len = 0; \ + unsigned int __dynamic_len_idx = 0; \ + \ + if (0) \ + (void) __dynamic_len_idx; /* don't warn if unused */\ + _fields \ + return __event_len; \ +} + #undef DECLARE_EVENT_CLASS #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ static inline size_t __event_get_size__##_name(size_t *__dynamic_len, _proto) \ @@ -470,12 +569,29 @@ 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, \ + __struct_get_align__##_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, _fields) \ +static inline size_t __struct_get_align__##_provider##_name(_proto) \ +{ \ + size_t __event_align = 1; \ + _fields \ + return __event_align; \ +} + #undef DECLARE_EVENT_CLASS #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ static inline size_t __event_get_align__##_name(_proto) \ @@ -517,6 +633,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 @@ -568,6 +687,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 +748,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, dest, src) \ +__assign_##dest: \ + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__typemap.dest));\ + __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(dest, src) \ + tp_memcpy_struct_gen(event_write, 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
