From: Jonathan Rajotte Date: Mon, 11 Feb 2019 16:18:22 +0000 (-0500) Subject: Sessiond: Implement cmd_clear_session X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=38cd0ad9f99bedeffd9fa659943f1fe050b7a16a Sessiond: Implement cmd_clear_session Signed-off-by: Jonathan Rajotte --- diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index e6ad3d262..147e0a1dd 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -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 */ diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 6fc18097f..7183bf195 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -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 index 000000000..a0917dca8 --- /dev/null +++ b/src/bin/lttng-sessiond/clear.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 - Jonathan Rajotte + * + * 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 +#include +#include +#include + +#include +#include +#include + +#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 index 000000000..bcaa2e116 --- /dev/null +++ b/src/bin/lttng-sessiond/clear.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 - Jonathan Rajotte + * + * 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 */ diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 5cbd42f63..382815e6b 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -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; +} diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index 99990714a..f81a328f8 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -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 */ diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 8892e76dc..f8dcd718f 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -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; +} diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 1b394947b..829ec0e3e 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -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, diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 62a6e9c09..81edd21c2 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -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; +} diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index 3c375f30d..9d455c85d 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -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 */ diff --git a/src/common/error.c b/src/common/error.c index eed6aecaf..c79ce5713 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -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" diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 7db241166..7842a2122 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -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 */