+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;
+ }
+}
+