#define LTTNG_UST_UUID_LEN 16
+/*
+ * Tracepoint provider version. Compatibility based on the major number.
+ * Older tracepoint providers can always register to newer lttng-ust
+ * library, but the opposite is rejected: a newer tracepoint provider is
+ * rejected by an older lttng-ust library.
+ */
+#define LTTNG_UST_PROVIDER_MAJOR 1
+#define LTTNG_UST_PROVIDER_MINOR 0
+
struct lttng_channel;
struct lttng_session;
struct lttng_ust_lib_ring_buffer_ctx;
} u;
};
-#define LTTNG_UST_PROBE_DESC_PADDING 20
+#define LTTNG_UST_PROBE_DESC_PADDING 12
struct lttng_probe_desc {
const char *provider;
const struct lttng_event_desc **event_desc;
struct cds_list_head head; /* chain registered probes */
struct cds_list_head lazy_init_head;
int lazy; /* lazy registration */
+ uint32_t major;
+ uint32_t minor;
char padding[LTTNG_UST_PROBE_DESC_PADDING];
};
.provider = __tp_stringify(TRACEPOINT_PROVIDER),
.event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER),
.nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)),
+ .major = LTTNG_UST_PROVIDER_MAJOR,
+ .minor = LTTNG_UST_PROVIDER_MINOR,
};
/*
return NULL;
}
+static
+int check_provider_version(struct lttng_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, 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, desc->major, desc->minor,
+ LTTNG_UST_PROVIDER_MAJOR,
+ LTTNG_UST_PROVIDER_MINOR);
+ return 0; /* reject */
+ }
+}
+
+
int lttng_probe_register(struct lttng_probe_desc *desc)
{
int ret = 0;
+ /*
+ * If version mismatch, don't register, but don't trigger assert
+ * on caller. The version check just prints an error.
+ */
+ if (!check_provider_version(desc))
+ return 0;
+
ust_lock();
/*
void lttng_probe_unregister(struct lttng_probe_desc *desc)
{
+ if (!check_provider_version(desc))
+ return;
+
ust_lock();
if (!desc->lazy)
cds_list_del(&desc->head);