[lttng-dev] [RFC-patch] Add support of struct metadata in tracepoints
Geneviève Bastien
gbastien+lttng at versatic.net
Thu Apr 11 16:07:31 EDT 2013
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 <gbastien+lttng at versatic.net>
---
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
More information about the lttng-dev
mailing list