X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ust%2Flttng-probes.c;h=2d47bf19c050e475ca0a506e5dff1d5e17adf5bf;hb=c246521ddcba1d1d28cfa0482aa500b9122e7264;hp=4552e5e82880d48f800093675f3986b4f6a30cba;hpb=7f2f82c3b336458e815e9a4ed100d7084c9e7138;p=lttng-ust.git diff --git a/src/lib/lttng-ust/lttng-probes.c b/src/lib/lttng-ust/lttng-probes.c index 4552e5e8..2d47bf19 100644 --- a/src/lib/lttng-ust/lttng-probes.c +++ b/src/lib/lttng-ust/lttng-probes.c @@ -39,17 +39,98 @@ static CDS_LIST_HEAD(lazy_probe_init); */ static int lazy_nesting; +static +int check_provider_version(const struct lttng_ust_probe_desc *desc) +{ + /* + * Check tracepoint provider version compatibility. + */ + if (desc->major <= LTTNG_UST_PROVIDER_MAJOR && + desc->major >= LTTNG_UST_PROVIDER_MAJOR_OLDEST_COMPATIBLE) { + DBG("Provider \"%s\" accepted, version %u.%u is compatible " + "with LTTng UST provider version %u.%u.", + desc->provider_name, desc->major, desc->minor, + LTTNG_UST_PROVIDER_MAJOR, + LTTNG_UST_PROVIDER_MINOR); + if (desc->major < LTTNG_UST_PROVIDER_MAJOR) { + DBG("However, some LTTng UST features might not be " + "available for this provider unless it is " + "recompiled against a more recent LTTng UST."); + } + return 1; /* accept */ + } else { + ERR("Provider \"%s\" rejected, version %u.%u is incompatible " + "with LTTng UST provider version %u.%u. Please upgrade " + "LTTng UST.", + desc->provider_name, desc->major, desc->minor, + LTTNG_UST_PROVIDER_MAJOR, + LTTNG_UST_PROVIDER_MINOR); + return 0; /* reject */ + } +} + +static +bool check_type_provider(const struct lttng_ust_type_common *type); + +static +bool check_type_provider(const struct lttng_ust_type_common *type) +{ + switch (type->type) { + case lttng_ust_type_integer: + return true; + case lttng_ust_type_string: + return true; + case lttng_ust_type_float: + return true; + case lttng_ust_type_dynamic: + return true; + case lttng_ust_type_enum: + { + const struct lttng_ust_type_enum *enum_type = caa_container_of(type, const struct lttng_ust_type_enum, parent); + + return check_provider_version(enum_type->desc->probe_desc); + } + case lttng_ust_type_array: + { + const struct lttng_ust_type_array *array_type = caa_container_of(type, const struct lttng_ust_type_array, parent); + + return check_type_provider(array_type->elem_type); + } + case lttng_ust_type_sequence: + { + const struct lttng_ust_type_sequence *sequence_type = caa_container_of(type, const struct lttng_ust_type_sequence, parent); + + return check_type_provider(sequence_type->elem_type); + } + case lttng_ust_type_struct: + { + const struct lttng_ust_type_struct *struct_type = caa_container_of(type, const struct lttng_ust_type_struct, parent); + size_t i; + + for (i = 0; i < struct_type->nr_fields; i++) { + if (!check_type_provider(struct_type->fields[i]->type)) + return false; + } + return true; + } + default: + return false; + } +} + /* * Validate that each event within the probe provider refers to the - * right probe, and that the resulting name is not too long. + * right probe, that the resulting name is not too long, and that the + * event class belongs to a provider with compatible version. */ static bool check_event_provider(const struct lttng_ust_probe_desc *probe_desc) { - int i; + int i, j; for (i = 0; i < probe_desc->nr_events; i++) { const struct lttng_ust_event_desc *event_desc = probe_desc->event_desc[i]; + const struct lttng_ust_tracepoint_class *tp_class = event_desc->tp_class; if (event_desc->probe_desc != probe_desc) { ERR("Error registering probe provider '%s'. Event '%s:%s' refers to the wrong provider descriptor.", @@ -61,6 +142,20 @@ bool check_event_provider(const struct lttng_ust_probe_desc *probe_desc) probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name); return false; /* provider mismatch */ } + if (!check_provider_version(tp_class->probe_desc)) { + ERR("Error registering probe provider '%s'. Event '%s:%s' refers to an event class in a provider with incompatible version.", + probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name); + return false; + } + for (j = 0; j < tp_class->nr_fields; j++) { + const struct lttng_ust_event_field *field = tp_class->fields[j]; + + if (!check_type_provider(field->type)) { + ERR("Error registering probe provider '%s'. Event '%s:%s' contains a field which refers to an provider with incompatible version.", + probe_desc->provider_name, probe_desc->provider_name, event_desc->event_name); + return false; + } + } } return true; } @@ -131,40 +226,12 @@ struct cds_list_head *lttng_get_probe_list_head(void) return &_probe_list; } -static -int check_provider_version(const struct lttng_ust_probe_desc *desc) -{ - /* - * Check tracepoint provider version compatibility. - */ - if (desc->major <= LTTNG_UST_PROVIDER_MAJOR) { - DBG("Provider \"%s\" accepted, version %u.%u is compatible " - "with LTTng UST provider version %u.%u.", - desc->provider_name, desc->major, desc->minor, - LTTNG_UST_PROVIDER_MAJOR, - LTTNG_UST_PROVIDER_MINOR); - if (desc->major < LTTNG_UST_PROVIDER_MAJOR) { - DBG("However, some LTTng UST features might not be " - "available for this provider unless it is " - "recompiled against a more recent LTTng UST."); - } - return 1; /* accept */ - } else { - ERR("Provider \"%s\" rejected, version %u.%u is incompatible " - "with LTTng UST provider version %u.%u. Please upgrade " - "LTTng UST.", - desc->provider_name, desc->major, desc->minor, - LTTNG_UST_PROVIDER_MAJOR, - LTTNG_UST_PROVIDER_MINOR); - return 0; /* reject */ - } -} struct lttng_ust_registered_probe *lttng_ust_probe_register(const struct lttng_ust_probe_desc *desc) { struct lttng_ust_registered_probe *reg_probe = NULL; - lttng_ust_fixup_tls(); + lttng_ust_common_init_thread(0); /* * If version mismatch, don't register, but don't trigger assert @@ -202,7 +269,7 @@ end: void lttng_ust_probe_unregister(struct lttng_ust_registered_probe *reg_probe) { - lttng_ust_fixup_tls(); + lttng_ust_common_init_thread(0); if (!reg_probe) return; @@ -259,7 +326,7 @@ int lttng_probes_get_event_list(struct lttng_ust_tracepoint_list *list) cds_list_add(&list_entry->head, &list->head); lttng_ust_format_event_name(event_desc, list_entry->tp.name); if (!event_desc->loglevel) { - list_entry->tp.loglevel = TRACE_DEFAULT; + list_entry->tp.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT; } else { list_entry->tp.loglevel = *(*event_desc->loglevel); } @@ -326,7 +393,7 @@ int lttng_probes_get_field_list(struct lttng_ust_field_list *list) probe_desc->event_desc[i]; int j; - if (event_desc->nr_fields == 0) { + if (event_desc->tp_class->nr_fields == 0) { /* Events without fields. */ struct tp_field_list_entry *list_entry; @@ -341,16 +408,16 @@ int lttng_probes_get_field_list(struct lttng_ust_field_list *list) list_entry->field.field_name[0] = '\0'; list_entry->field.type = LTTNG_UST_ABI_FIELD_OTHER; if (!event_desc->loglevel) { - list_entry->field.loglevel = TRACE_DEFAULT; + list_entry->field.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT; } else { list_entry->field.loglevel = *(*event_desc->loglevel); } list_entry->field.nowrite = 1; } - for (j = 0; j < event_desc->nr_fields; j++) { + for (j = 0; j < event_desc->tp_class->nr_fields; j++) { const struct lttng_ust_event_field *event_field = - event_desc->fields[j]; + event_desc->tp_class->fields[j]; struct tp_field_list_entry *list_entry; /* Skip event if name is too long. */ @@ -394,7 +461,7 @@ int lttng_probes_get_field_list(struct lttng_ust_field_list *list) list_entry->field.type = LTTNG_UST_ABI_FIELD_OTHER; } if (!event_desc->loglevel) { - list_entry->field.loglevel = TRACE_DEFAULT; + list_entry->field.loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT; } else { list_entry->field.loglevel = *(*event_desc->loglevel); }