Fix: add provider ABI compatibility check
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 8 May 2013 18:52:42 +0000 (14:52 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 8 May 2013 18:52:42 +0000 (14:52 -0400)
There is not much we can do for this compatibility bug in lttng-ust 2.0
and 2.1 (already stable). Adding this check so that starting with
lttng-ust 2.2, when liblttng-ust encounters a probe provider with a
provider version major number higher than it supports, it will reject
it.

Fixes #502

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-events.h
include/lttng/ust-tracepoint-event.h
liblttng-ust/lttng-probes.c

index 749478a6a335b3b9b14ab0ceb3dd87787f469b30..0b8664c3cbae0635c441f777e11d4d359e21ba5d 100644 (file)
 
 #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;
@@ -251,7 +260,7 @@ struct lttng_event_desc {
        } 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;
@@ -259,6 +268,8 @@ struct lttng_probe_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];
 };
 
index e46cc1a1a28cc4d9c440a3ccb816d79ef530e840..c7bceef652478d4ba114788867ed98941d34379a 100644 (file)
@@ -652,6 +652,8 @@ static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PR
        .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,
 };
 
 /*
index f028ccab8cadd967971cb3f673b883f622b03f7e..433171cfb04635c424394a9e2c292f82a70a8ae4 100644 (file)
@@ -160,10 +160,47 @@ const struct lttng_probe_desc *find_provider(const char *provider)
        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();
 
        /*
@@ -197,6 +234,9 @@ int ltt_probe_register(struct lttng_probe_desc *desc)
 
 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);
This page took 0.02721 seconds and 4 git commands to generate.