Add userspace time namespace context
authorMichael Jeanson <mjeanson@efficios.com>
Mon, 6 Jul 2020 15:48:16 +0000 (11:48 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 7 Jul 2020 20:53:50 +0000 (16:53 -0400)
This was introduced in kernel v5.6.0, on a system running an older kernel,
zero will be returned.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I1ea66a98c96a4de084c02521f6982e8c7d1b53bb

doc/man/lttng-ust.3.txt
include/lttng/ust-abi.h
include/lttng/ust-events.h
liblttng-ust/Makefile.am
liblttng-ust/lttng-context-time-ns.c [new file with mode: 0644]
liblttng-ust/lttng-context.c
liblttng-ust/lttng-events.c
liblttng-ust/lttng-tracer-core.h
liblttng-ust/lttng-ust-comm.c

index 507aaca5e0ac070328eff4cdee587f1181240015..9b86906a185d058c47a8a3ded278e948288be08f 100644 (file)
@@ -818,6 +818,10 @@ The following man:namespaces(7) context fields are supported by LTTng-UST:
     Process IDs namespace: inode number of the current
     man:pid_namespaces(7) in the proc filesystem.
 
+`time_ns`::
+    Time and system clock namespace: inode number of the current
+    man:time_namespaces(7) in the proc filesystem.
+
 `user_ns`::
     User and group IDs namespace: inode number of the current
     man:user_namespaces(7) in the proc filesystem.
index a823de542feac84147228e232b76533bcfa06394..8bf77f64bb036106cc055d97fa2d0acb678d55f3 100644 (file)
@@ -159,6 +159,7 @@ enum lttng_ust_context_type {
        LTTNG_UST_CONTEXT_VGID                  = 18,
        LTTNG_UST_CONTEXT_VEGID                 = 19,
        LTTNG_UST_CONTEXT_VSGID                 = 20,
+       LTTNG_UST_CONTEXT_TIME_NS               = 21,
 };
 
 struct lttng_ust_perf_counter_ctx {
index b050d30ec03af5d0b435f27dae85a0c71a5d16b5..3fee93c435038acf3150759aa7d5c964bd38e448 100644 (file)
@@ -735,6 +735,7 @@ int lttng_add_ipc_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_mnt_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_net_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_pid_ns_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_time_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_user_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_uts_ns_to_ctx(struct lttng_ctx **ctx);
 int lttng_add_vuid_to_ctx(struct lttng_ctx **ctx);
@@ -751,6 +752,7 @@ void lttng_context_ipc_ns_reset(void);
 void lttng_context_mnt_ns_reset(void);
 void lttng_context_net_ns_reset(void);
 void lttng_context_pid_ns_reset(void);
+void lttng_context_time_ns_reset(void);
 void lttng_context_user_ns_reset(void);
 void lttng_context_uts_ns_reset(void);
 void lttng_context_vuid_reset(void);
index abb7a8dc4154166f85ffb4c40e2c5239b89cbe49..3f4c023db24acaaf646259982dfcacd0491ed92e 100644 (file)
@@ -38,6 +38,7 @@ liblttng_ust_runtime_la_SOURCES = \
        lttng-context-mnt-ns.c \
        lttng-context-net-ns.c \
        lttng-context-pid-ns.c \
+       lttng-context-time-ns.c \
        lttng-context-user-ns.c \
        lttng-context-uts-ns.c \
        lttng-context-vuid.c \
diff --git a/liblttng-ust/lttng-context-time-ns.c b/liblttng-ust/lttng-context-time-ns.c
new file mode 100644 (file)
index 0000000..dda8fb3
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * lttng-context-time-ns.c
+ *
+ * LTTng UST time namespace context.
+ *
+ * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *               2020 Michael Jeanson <mjeanson@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <lttng/ust-tid.h>
+#include <urcu/tls-compat.h>
+#include "lttng-tracer-core.h"
+#include "ns.h"
+
+
+/*
+ * We cache the result to ensure we don't stat(2) the proc filesystem on
+ * each event.
+ */
+static DEFINE_URCU_TLS_INIT(ino_t, cached_time_ns, NS_INO_UNINITIALIZED);
+
+static
+ino_t get_time_ns(void)
+{
+       struct stat sb;
+       ino_t time_ns;
+
+       time_ns = CMM_LOAD_SHARED(URCU_TLS(cached_time_ns));
+
+       /*
+        * If the cache is populated, do nothing and return the
+        * cached inode number.
+        */
+       if (caa_likely(time_ns != NS_INO_UNINITIALIZED))
+               return time_ns;
+
+       /*
+        * At this point we have to populate the cache, set the initial
+        * value to NS_INO_UNAVAILABLE (0), if we fail to get the inode
+        * number from the proc filesystem, this is the value we will
+        * cache.
+        */
+       time_ns = NS_INO_UNAVAILABLE;
+
+       /*
+        * /proc/thread-self was introduced in kernel v3.17
+        */
+       if (stat("/proc/thread-self/ns/time", &sb) == 0) {
+               time_ns = sb.st_ino;
+       } else {
+               char proc_ns_path[LTTNG_PROC_NS_PATH_MAX];
+
+               if (snprintf(proc_ns_path, LTTNG_PROC_NS_PATH_MAX,
+                               "/proc/self/task/%d/ns/time",
+                               lttng_gettid()) >= 0) {
+
+                       if (stat(proc_ns_path, &sb) == 0) {
+                               time_ns = sb.st_ino;
+                       }
+               }
+       }
+
+       /*
+        * And finally, store the inode number in the cache.
+        */
+       CMM_STORE_SHARED(URCU_TLS(cached_time_ns), time_ns);
+
+       return time_ns;
+}
+
+/*
+ * The time namespace can change for 2 reasons
+ *  * setns(2) called with the fd of a different time ns
+ *  * clone(2) / fork(2) after a call to unshare(2) with the CLONE_NEWTIME flag
+ */
+void lttng_context_time_ns_reset(void)
+{
+       CMM_STORE_SHARED(URCU_TLS(cached_time_ns), NS_INO_UNINITIALIZED);
+}
+
+static
+size_t time_ns_get_size(struct lttng_ctx_field *field, size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(ino_t));
+       size += sizeof(ino_t);
+       return size;
+}
+
+static
+void time_ns_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct lttng_channel *chan)
+{
+       ino_t time_ns;
+
+       time_ns = get_time_ns();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(time_ns));
+       chan->ops->event_write(ctx, &time_ns, sizeof(time_ns));
+}
+
+static
+void time_ns_get_value(struct lttng_ctx_field *field,
+               struct lttng_ctx_value *value)
+{
+       value->u.s64 = get_time_ns();
+}
+
+int lttng_add_time_ns_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "time_ns")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "time_ns";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.integer.size = sizeof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.integer.alignment = lttng_alignof(ino_t) * CHAR_BIT;
+       field->event_field.type.u.integer.signedness = lttng_is_signed_type(ino_t);
+       field->event_field.type.u.integer.reverse_byte_order = 0;
+       field->event_field.type.u.integer.base = 10;
+       field->event_field.type.u.integer.encoding = lttng_encode_none;
+       field->get_size = time_ns_get_size;
+       field->record = time_ns_record;
+       field->get_value = time_ns_get_value;
+       lttng_context_update(*ctx);
+       return 0;
+}
+
+/*
+ *  * Force a read (imply TLS fixup for dlopen) of TLS variables.
+ *   */
+void lttng_fixup_time_ns_tls(void)
+{
+       asm volatile ("" : : "m" (URCU_TLS(cached_time_ns)));
+}
index 5637028bed1bdd35d38715ad68afc33673652c50..fc564b6aa5745bd1fbacb75118fd5619b3077ecf 100644 (file)
@@ -454,6 +454,11 @@ int lttng_session_context_init(struct lttng_ctx **ctx)
                WARN("Cannot add context lttng_add_pid_ns_to_ctx");
                goto error;
        }
+       ret = lttng_add_time_ns_to_ctx(ctx);
+       if (ret) {
+               WARN("Cannot add context lttng_add_time_ns_to_ctx");
+               goto error;
+       }
        ret = lttng_add_user_ns_to_ctx(ctx);
        if (ret) {
                WARN("Cannot add context lttng_add_user_ns_to_ctx");
index cbed800bee95ef4bfb9b1ec4fbad3533618c30b7..627cd4e101df4280b5a44b96f4719301c265df9b 100644 (file)
@@ -1145,6 +1145,8 @@ int lttng_attach_context(struct lttng_ust_context *context_param,
                return lttng_add_net_ns_to_ctx(ctx);
        case LTTNG_UST_CONTEXT_PID_NS:
                return lttng_add_pid_ns_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_TIME_NS:
+               return lttng_add_time_ns_to_ctx(ctx);
        case LTTNG_UST_CONTEXT_USER_NS:
                return lttng_add_user_ns_to_ctx(ctx);
        case LTTNG_UST_CONTEXT_UTS_NS:
index 1a0f03a181657c18ccebbdf8ed81070c57dbedd6..bce6c2397cd22797b6d7c7104ac107e63b2e90cb 100644 (file)
@@ -55,6 +55,7 @@ void lttng_fixup_procname_tls(void);
 void lttng_fixup_cgroup_ns_tls(void);
 void lttng_fixup_ipc_ns_tls(void);
 void lttng_fixup_net_ns_tls(void);
+void lttng_fixup_time_ns_tls(void);
 void lttng_fixup_uts_ns_tls(void);
 
 const char *lttng_ust_obj_get_name(int id);
index 900a0e840861f78d7a826abc0ed176b0960a0435..3847c9767d97d9d7e99f8ecf98208877f17ac917 100644 (file)
@@ -434,6 +434,7 @@ void lttng_ust_fixup_tls(void)
        lttng_fixup_cgroup_ns_tls();
        lttng_fixup_ipc_ns_tls();
        lttng_fixup_net_ns_tls();
+       lttng_fixup_time_ns_tls();
        lttng_fixup_uts_ns_tls();
 }
 
@@ -2065,6 +2066,7 @@ void ust_context_ns_reset(void)
        lttng_context_mnt_ns_reset();
        lttng_context_net_ns_reset();
        lttng_context_user_ns_reset();
+       lttng_context_time_ns_reset();
        lttng_context_uts_ns_reset();
 }
 
This page took 0.030464 seconds and 4 git commands to generate.