Sessiond: Implement cmd_clear_session
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Mon, 11 Feb 2019 16:18:22 +0000 (11:18 -0500)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Wed, 10 Apr 2019 20:20:10 +0000 (16:20 -0400)
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
12 files changed:
include/lttng/lttng-error.h
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/clear.c [new file with mode: 0644]
src/bin/lttng-sessiond/clear.h [new file with mode: 0644]
src/bin/lttng-sessiond/consumer.c
src/bin/lttng-sessiond/consumer.h
src/bin/lttng-sessiond/kernel.c
src/bin/lttng-sessiond/kernel.h
src/bin/lttng-sessiond/ust-app.c
src/bin/lttng-sessiond/ust-app.h
src/common/error.c
src/common/sessiond-comm/sessiond-comm.h

index e6ad3d262c290c371146518eedb8e22ad39b1d5a..147e0a1dd8ff29821c1ce884664b7842c09ed885 100644 (file)
@@ -150,6 +150,13 @@ enum lttng_error_code {
        LTTNG_ERR_TRIGGER_NOT_FOUND      = 127, /* Trigger not found. */
        LTTNG_ERR_COMMAND_CANCELLED      = 128, /* Command cancelled. */
        LTTNG_ERR_AGENT_TRACING_DISABLED = 139, /* Agent tracing disabled. */
+       LTTNG_ERR_USER_NOT_FOUND = 140, /* User not found. */
+       LTTNG_ERR_GROUP_NOT_FOUND = 141, /* Group not found. */
+       LTTNG_ERR_CHAN_NOT_FOUND         = 146, /* Channel not found */
+       LTTNG_ERR_CLEAR_RELAY_DISALLOW   = 147, /* LTTng-relayd peer does not allow lttng clear command. */
+       LTTNG_ERR_CLEAR_NOT_AVAILABLE    = 148, /* Clear feature not available. */
+       LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY = 149, /* Clear feature not available on the relay. */
+       LTTNG_ERR_CLEAR_FAIL_CONSUMER    = 150, /* Clear failure on consumer */
 
        /* MUST be last element */
        LTTNG_ERR_NR,                           /* Last element */
index 6fc18097f134eb5f97f94a8ac34489e452445408..7183bf1953b337c773129a3378681c77d6b1490f 100644 (file)
@@ -35,7 +35,8 @@ lttng_sessiond_SOURCES = utils.c utils.h \
                        notification-thread.h notification-thread.c \
                        notification-thread-commands.h notification-thread-commands.c \
                        notification-thread-events.h notification-thread-events.c \
-                       sessiond-config.h sessiond-config.c
+                       sessiond-config.h sessiond-config.c \
+                       clear.c
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \
diff --git a/src/bin/lttng-sessiond/clear.c b/src/bin/lttng-sessiond/clear.c
new file mode 100644 (file)
index 0000000..a0917dc
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <common/defaults.h>
+#include <common/error.h>
+#include <common/utils.h>
+
+#include "clear.h"
+#include "session.h"
+#include "ust-app.h"
+#include "kernel.h"
+
+
+int cmd_clear_session(struct ltt_session *session)
+{
+       int ret;
+
+       if (!session->has_been_started) {
+                /* Nothing to be cleared, do not warn */
+                ret = LTTNG_OK;
+                goto end;
+       }
+
+       /*
+        * Unsupported feature in lttng-relayd before 2.12.
+        */
+       if (session->consumer->type == CONSUMER_DST_NET &&
+                       (session->consumer->relay_major_version == 2 &&
+                       session->consumer->relay_minor_version < 12)) {
+               ret = LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY;
+               goto end;
+       }
+
+       /* TODO: Should we check for disallowed here or consumer side? */
+
+       /* Snapshot session are the only one supported for now */
+       if (!session->snapshot_mode) {
+               /*
+                * TODO: this error code is temporary and will be removed since
+                * we will be supporting all session type
+                */
+               ret = LTTNG_ERR_CLEAR_NOT_AVAILABLE;
+               goto end;
+       }
+
+       if (session->kernel_session) {
+               ret = kernel_clear_session(session);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+       }
+       if (session->ust_session) {
+               ret = ust_app_clear_session(session);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+       }
+error:
+end:
+       return ret;
+}
diff --git a/src/bin/lttng-sessiond/clear.h b/src/bin/lttng-sessiond/clear.h
new file mode 100644 (file)
index 0000000..bcaa2e1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 - Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CLEAR_H
+#define CLEAR_H
+
+#include "session.h"
+
+int cmd_clear_session(struct ltt_session *session);
+
+#endif /* CLEAT_H */
index 5cbd42f6301d327abefdb159541dc7f651983e9d..382815e6b3665ecb76cde7ce1edf5fbc37c4fe3f 100644 (file)
@@ -1573,3 +1573,38 @@ end:
        rcu_read_unlock();
        return ret;
 }
+
+int consumer_clear_channel(struct consumer_socket *socket, uint64_t key,
+               struct consumer_output *output)
+{
+       int ret;
+       struct lttcomm_consumer_msg msg;
+
+       assert(socket);
+
+       DBG("Consumer clear channel %" PRIu64, key);
+
+       memset(&msg, 0, sizeof(msg));
+       msg.cmd_type = LTTNG_CONSUMER_CLEAR_CHANNEL;
+       msg.u.clear_channel.key = key;
+
+       if (output->type == CONSUMER_DST_NET) {
+               ERR("Relayd clear is not supported for now");
+               ret = -LTTNG_ERR_INVALID;
+               goto error;
+       }
+       health_code_update();
+
+       pthread_mutex_lock(socket->lock);
+       ret = consumer_send_msg(socket, &msg);
+       if (ret < 0) {
+               goto error_socket;
+       }
+
+error_socket:
+       pthread_mutex_unlock(socket->lock);
+
+error:
+       health_code_update();
+       return ret;
+}
index 99990714ac61e80039a80e77ba04953d55c2a495..f81a328f89ce7b253182761c7e0495b6affeca29 100644 (file)
@@ -305,4 +305,7 @@ int consumer_snapshot_channel(struct consumer_socket *socket, uint64_t key,
                struct snapshot_output *output, int metadata, uid_t uid, gid_t gid,
                const char *session_path, int wait, uint64_t nb_packets_per_stream);
 
+/* Clear command */
+int consumer_clear_channel(struct consumer_socket *socket, uint64_t key,
+               struct consumer_output *output);
 #endif /* _CONSUMER_H */
index 8892e76dc144f7963be7813647df05e5f9006da1..f8dcd718fc3cb73ce14d3ce5c5dc84a4a72800e4 100644 (file)
@@ -1122,3 +1122,70 @@ int kernel_supports_ring_buffer_snapshot_sample_positions(int tracer_fd)
 error:
        return ret;
 }
+
+/*
+ *  Clear a kernel session.
+ *
+ * Return LTTNG_OK on success or else an LTTng error code.
+ */
+enum lttng_error_code kernel_clear_session(struct ltt_session *session)
+{
+       int ret;
+       enum lttng_error_code status = LTTNG_OK;
+       struct consumer_socket *socket;
+       struct lttng_ht_iter iter;
+       struct ltt_kernel_session *ksess = session->kernel_session;
+
+       assert(ksess);
+       assert(ksess->consumer);
+
+       DBG("Cleat kernel session %s (session %" PRIu64 ")",
+                       session->name, session->id);
+
+       rcu_read_lock();
+
+       /*
+        * Note that this loop will end after one iteration given that there is
+        * only one kernel consumer.
+        */
+       cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter,
+                       socket, node.node) {
+               struct ltt_kernel_channel *chan;
+
+               /* For each channel, ask the consumer to clear it. */
+               cds_list_for_each_entry(chan, &ksess->channel_list.head, list) {
+                       DBG("Clear kernel channel %" PRIu64 ", session %s",
+                                       chan->key, session->name);
+                       ret = consumer_clear_channel(socket, chan->key,
+                                       ksess->consumer);
+                       if (ret < 0) {
+                               goto error;
+                       }
+               }
+
+               /*
+                * Clear the metadata channel.
+                * Metadata channel is not cleared per se but we still need to
+                * perform rotation operation on it behind the scene.
+                */
+               ret = consumer_clear_channel(socket, ksess->metadata->key,
+                               ksess->consumer);
+               if (ret < 0) {
+                       goto error;
+               }
+       }
+
+       goto end;
+error:
+       switch (-ret) {
+       case LTTCOMM_CONSUMERD_RELAYD_DISALLOW_CLEAR:
+             status = LTTNG_ERR_CLEAR_RELAY_DISALLOW;
+             break;
+       default:
+             status = LTTNG_ERR_CLEAR_FAIL_CONSUMER;
+             break;
+       }
+end:
+       rcu_read_unlock();
+       return status;
+}
index 1b394947b31f8c4c2c4ca6cc88efbc291c6a8db6..829ec0e3e6148ecb51d4378af8c7f214a623b000 100644 (file)
@@ -61,6 +61,7 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess,
                struct snapshot_output *output, int wait,
                uint64_t nb_packets_per_stream);
 int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits);
+enum lttng_error_code kernel_clear_session(struct ltt_session *session);
 
 int init_kernel_workarounds(void);
 ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session,
index 62a6e9c0916467772ecb96511e1f712cd26edcc9..81edd21c2d671e1e1c2cf78fc8cb2f4afe0ee8b3 100644 (file)
@@ -6275,3 +6275,149 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
 
        return 0;
 }
+
+/*
+ * Clear all the channels of a session.
+ *
+ * Return LTTNG_OK on success or else an LTTng error code.
+ */
+enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
+{
+       int ret;
+       enum lttng_error_code cmd_ret = LTTNG_OK;
+       struct lttng_ht_iter iter;
+       struct ust_app *app;
+       struct ltt_ust_session *usess = session->ust_session;
+
+       assert(usess);
+
+       rcu_read_lock();
+
+       switch (usess->buffer_type) {
+       case LTTNG_BUFFER_PER_UID:
+       {
+               struct buffer_reg_uid *reg;
+
+               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+                       struct buffer_reg_channel *reg_chan;
+                       struct consumer_socket *socket;
+
+                       /* Get consumer socket to use to push the metadata.*/
+                       socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               cmd_ret = LTTNG_ERR_INVALID;
+                               goto error_socket;
+                       }
+
+                       /* Clear the data channels. */
+                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
+                                       reg_chan, node.node) {
+                               ret = consumer_clear_channel(socket,
+                                               reg_chan->consumer_key,
+                                               usess->consumer);
+                               if (ret < 0) {
+                                       goto error;
+                               }
+                       }
+
+                       (void) push_metadata(reg->registry->reg.ust, usess->consumer);
+
+                       /*
+                        * Clear the metadata channel.
+                        * Metadata channel is not cleared per se but we still need to
+                        * perform rotation operation on it behind the scene.
+                        */
+                       ret = consumer_clear_channel(socket,
+                                       reg->registry->reg.ust->metadata_key,
+                                       usess->consumer);
+                       if (ret < 0) {
+                               goto error;
+                       }
+               }
+               break;
+       }
+       case LTTNG_BUFFER_PER_PID:
+       {
+               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct consumer_socket *socket;
+                       struct lttng_ht_iter chan_iter;
+                       struct ust_app_channel *ua_chan;
+                       struct ust_app_session *ua_sess;
+                       struct ust_registry_session *registry;
+
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (!ua_sess) {
+                               /* Session not associated with this app. */
+                               continue;
+                       }
+
+                       /* Get the right consumer socket for the application. */
+                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
+                                       usess->consumer);
+                       if (!socket) {
+                               cmd_ret = LTTNG_ERR_INVALID;
+                               goto error_socket;
+                       }
+
+                       registry = get_session_registry(ua_sess);
+                       if (!registry) {
+                               DBG("Application session is being torn down. Skip application.");
+                               continue;
+                       }
+
+                       /* Rotate the data channels. */
+                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
+                                       ua_chan, node.node) {
+                               ret = consumer_clear_channel(socket, ua_chan->key,
+                                               ua_sess->consumer);
+                               if (ret < 0) {
+                                       /* Per-PID buffer and application going away. */
+                                       if (ret == -LTTNG_ERR_CHAN_NOT_FOUND) {
+                                               continue;
+                                       }
+                                       goto error;
+                               }
+                       }
+
+                       (void) push_metadata(registry, usess->consumer);
+
+                       /*
+                        * Clear the metadata channel.
+                        * Metadata channel is not cleared per se but we still need to
+                        * perform rotation operation on it behind the scene.
+                        */
+                       ret = consumer_clear_channel(socket, registry->metadata_key,
+                                       ua_sess->consumer);
+                       if (ret < 0) {
+                               /* Per-PID buffer and application going away. */
+                               if (ret == -LTTNG_ERR_CHAN_NOT_FOUND) {
+                                       continue;
+                               }
+                               goto error;
+                       }
+               }
+               break;
+       }
+       default:
+               assert(0);
+               break;
+       }
+
+       cmd_ret = LTTNG_OK;
+       goto end;
+
+error:
+       switch (-ret) {
+       case LTTCOMM_CONSUMERD_RELAYD_DISALLOW_CLEAR:
+               cmd_ret = LTTNG_ERR_CLEAR_RELAY_DISALLOW;
+               break;
+       default:
+               cmd_ret = LTTNG_ERR_CLEAR_FAIL_CONSUMER;
+       }
+
+error_socket:
+end:
+       rcu_read_unlock();
+       return cmd_ret;
+}
index 3c375f30d82e33513db0445d134da6931315463d..9d455c85d38ad22d5a8c882b561e0b25ea169b2f 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "trace-ust.h"
 #include "ust-registry.h"
+#include "session.h"
 
 #define UST_APP_EVENT_LIST_SIZE 32
 
@@ -357,6 +358,7 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                struct consumer_output *consumer,
                int overwrite, uint64_t *discarded, uint64_t *lost);
 int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess);
+enum lttng_error_code ust_app_clear_session(struct ltt_session *session);
 
 static inline
 int ust_app_supported(void)
@@ -590,6 +592,12 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
        return 0;
 }
 
+static inline
+enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
+{
+       return 0;
+}
+
 #endif /* HAVE_LIBLTTNG_UST_CTL */
 
 #endif /* _LTT_UST_APP_H */
index eed6aecaf14af22efbd20460db6c49704aa500a9..c79ce571319e4e23a382007ba99b6d120a77a1d7 100644 (file)
@@ -191,6 +191,12 @@ static const char *error_string_array[] = {
        [ ERROR_INDEX(LTTNG_ERR_TRIGGER_NOT_FOUND) ] = "Trigger not found",
        [ ERROR_INDEX(LTTNG_ERR_COMMAND_CANCELLED) ] = "Command cancelled",
        [ ERROR_INDEX(LTTNG_ERR_AGENT_TRACING_DISABLED) ] = "Session daemon agent tracing is disabled",
+       [ ERROR_INDEX(LTTNG_ERR_USER_NOT_FOUND) ] = "User not found.",
+       [ ERROR_INDEX(LTTNG_ERR_GROUP_NOT_FOUND) ] = "Group not found.",
+       [ ERROR_INDEX(LTTNG_ERR_CLEAR_RELAY_DISALLOW) ] = "Relayd daemon peer does not allow lttng clear command",
+       [ ERROR_INDEX(LTTNG_ERR_CLEAR_NOT_AVAILABLE) ] = "Clear feature is not available for the session type",
+       [ ERROR_INDEX(LTTNG_ERR_CLEAR_NOT_AVAILABLE_RELAY) ] = "Clear feature is not available on the relay",
+       [ ERROR_INDEX(LTTNG_ERR_CLEAR_FAIL_CONSUMER) ] = "Clear failure on the consumer",
 
        /* Last element */
        [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
index 7db2411669e38d2cbfd2203355936da0a2bdb38e..7842a2122b1165849231a3fae93c1d15a1b7b416 100644 (file)
@@ -151,6 +151,7 @@ enum lttcomm_return_code {
        LTTCOMM_CONSUMERD_CHANNEL_FAIL,             /* Channel creation failed. */
        LTTCOMM_CONSUMERD_CHAN_NOT_FOUND,           /* Channel not found. */
        LTTCOMM_CONSUMERD_ALREADY_SET,              /* Resource already set. */
+       LTTCOMM_CONSUMERD_RELAYD_DISALLOW_CLEAR,    /* Relayd does not accept clear command. */
 
        /* MUST be last element */
        LTTCOMM_NR,                                             /* Last element */
This page took 0.0337 seconds and 5 git commands to generate.