SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[lttng-tools.git] / src / common / userspace-probe.c
index 508c9e8d4480a8a99216e7a3792a6555dd534d3f..168b35015f9c81492d86d5f5fb02b6765ded5f7b 100644 (file)
@@ -6,12 +6,15 @@
  */
 
 #include <assert.h>
+#include <common/compat/string.h>
 #include <common/error.h>
 #include <common/macros.h>
-#include <common/compat/string.h>
 #include <fcntl.h>
 #include <lttng/constant.h>
 #include <lttng/userspace-probe-internal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/unistd.h>
 
 enum lttng_userspace_probe_location_lookup_method_type
 lttng_userspace_probe_location_lookup_method_get_type(
@@ -144,6 +147,88 @@ void lttng_userspace_probe_location_destroy(
        }
 }
 
+/*
+ * Compare two FDs.
+ * For now only the Inode number is compared.
+ */
+static bool fd_is_equal(int a, int b)
+{
+       int ret;
+       bool is_equal = false;
+       struct stat a_stat, b_stat;
+
+       if (a < 0 && b >= 0) {
+               goto end;
+       }
+
+       if (b < 0 && a >= 0) {
+               goto end;
+       }
+
+       if (a < 0 && b < 0) {
+               if (a == -1 && b == -1) {
+                       is_equal = true;
+                       goto end;
+               }
+               /* Invalid state, assert */
+               assert(0);
+               goto end;
+       }
+
+       /* Both are valid FD numbers */
+       ret = fstat(a, &a_stat);
+       if (ret) {
+               PERROR("fstat on fd a: %d", a);
+               goto end;
+       }
+
+       ret = fstat(b, &b_stat);
+       if (ret) {
+               PERROR("fstat on fd b: %d", b);
+               goto end;
+       }
+
+       is_equal = (a_stat.st_ino == b_stat.st_ino);
+
+end:
+       return is_equal;
+}
+
+static bool lttng_userspace_probe_location_function_is_equal(
+               const struct lttng_userspace_probe_location *_a,
+               const struct lttng_userspace_probe_location *_b)
+{
+       bool is_equal = false;
+       struct lttng_userspace_probe_location_function *a, *b;
+
+       a = container_of(_a, struct lttng_userspace_probe_location_function,
+                       parent);
+       b = container_of(_b, struct lttng_userspace_probe_location_function,
+                       parent);
+
+       if (a->instrumentation_type != b->instrumentation_type) {
+               goto end;
+       }
+
+       assert(a->function_name);
+       assert(b->function_name);
+       if (strcmp(a->function_name, b->function_name)) {
+               goto end;
+       }
+
+       assert(a->binary_path);
+       assert(b->binary_path);
+       if (strcmp(a->binary_path, b->binary_path)) {
+               goto end;
+       }
+
+       // TODO: see gerrit comment: https://review.lttng.org/c/lttng-tools/+/2924/27/src/common/userspace-probe.c#255
+       //is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
+       is_equal = true;
+end:
+       return is_equal;
+}
+
 static struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
                const char *function_name,
@@ -192,6 +277,7 @@ lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
        ret = &location->parent;
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
+       ret->equal = lttng_userspace_probe_location_function_is_equal;
        goto end;
 
 error:
@@ -206,6 +292,42 @@ end:
        return ret;
 }
 
+static bool lttng_userspace_probe_location_tracepoint_is_equal(
+               const struct lttng_userspace_probe_location *_a,
+               const struct lttng_userspace_probe_location *_b)
+{
+       bool is_equal = false;
+       struct lttng_userspace_probe_location_tracepoint *a, *b;
+
+       a = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+       b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
+                       parent);
+
+       assert(a->probe_name);
+       assert(b->probe_name);
+       if (strcmp(a->probe_name, b->probe_name)) {
+               goto end;
+       }
+
+       assert(a->provider_name);
+       assert(b->provider_name);
+       if (strcmp(a->provider_name, b->provider_name)) {
+               goto end;
+       }
+
+       assert(a->binary_path);
+       assert(b->binary_path);
+       if (strcmp(a->binary_path, b->binary_path)) {
+               goto end;
+       }
+
+       is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
+
+end:
+       return is_equal;
+}
+
 static struct lttng_userspace_probe_location *
 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path,
                const char *provider_name, const char *probe_name,
@@ -261,6 +383,7 @@ lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_pat
        ret = &location->parent;
        ret->lookup_method = lookup_method;
        ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
+       ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
        goto end;
 
 error:
@@ -1711,3 +1834,104 @@ struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
 err:
        return new_location;
 }
+
+LTTNG_HIDDEN
+bool lttng_userspace_probe_location_lookup_method_is_equal(
+               const struct lttng_userspace_probe_location_lookup_method *a,
+               const struct lttng_userspace_probe_location_lookup_method *b)
+{
+       bool is_equal = false;
+
+       if (!a || !b) {
+               goto end;
+       }
+
+       if (a == b) {
+               is_equal = true;
+               goto end;
+       }
+
+       /* Should we use the getter here? */
+       if (a->type != b->type) {
+               goto end;
+       }
+
+       /* Not much else to compare except the type for now */
+       is_equal = true;
+end:
+       return is_equal;
+}
+
+LTTNG_HIDDEN
+bool lttng_userspace_probe_location_is_equal(
+               const struct lttng_userspace_probe_location *a,
+               const struct lttng_userspace_probe_location *b)
+{
+       bool is_equal = false;
+
+       if (!a || !b) {
+               goto end;
+       }
+
+       if (a == b) {
+               is_equal = true;
+               goto end;
+       }
+
+       /* Should we use the getter here? */
+       if (!lttng_userspace_probe_location_lookup_method_is_equal(
+                           a->lookup_method, b->lookup_method)) {
+               goto end;
+       }
+
+       /* Should we use the getter here? */
+       if (a->type != b->type) {
+               goto end;
+       }
+
+       is_equal = a->equal ? a->equal(a, b) : true;
+end:
+       return is_equal;
+}
+
+LTTNG_HIDDEN
+int lttng_userspace_probe_location_set_binary_fd(
+               struct lttng_userspace_probe_location *location, int fd)
+{
+       int ret = 0;
+       const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
+       /*
+        * Set the file descriptor received from the client through the unix
+        * socket in the probe location.
+        */
+       lookup = lttng_userspace_probe_location_get_lookup_method(location);
+       if (!lookup) {
+               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+               goto end;
+       }
+
+       /*
+        * From the kernel tracer's perspective, all userspace probe event types
+        * are all the same: a file and an offset.
+        */
+       switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) {
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
+               ret = lttng_userspace_probe_location_function_set_binary_fd(
+                               location, fd);
+               break;
+       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
+               ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
+                               location, fd);
+               break;
+       default:
+               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+               goto end;
+       }
+
+       if (ret) {
+               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+               goto end;
+       }
+end:
+       return ret;
+}
This page took 0.029494 seconds and 5 git commands to generate.