From f3e3b7222f889a4e9f8936fc5ad3577400e4318d Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Mon, 11 Feb 2019 11:18:22 -0500 Subject: [PATCH] Sessiond: Implement cmd_clear_session Signed-off-by: Jonathan Rajotte --- include/lttng/lttng-error.h | 5 +- src/bin/lttng-sessiond/Makefile.am | 3 +- src/bin/lttng-sessiond/clear.c | 81 +++++++++++++ src/bin/lttng-sessiond/clear.h | 25 ++++ src/bin/lttng-sessiond/consumer.c | 35 ++++++ src/bin/lttng-sessiond/consumer.h | 3 + src/bin/lttng-sessiond/kernel.c | 67 +++++++++++ src/bin/lttng-sessiond/kernel.h | 1 + src/bin/lttng-sessiond/ust-app.c | 146 +++++++++++++++++++++++ src/bin/lttng-sessiond/ust-app.h | 7 ++ src/common/error.c | 4 + src/common/sessiond-comm/sessiond-comm.h | 1 + 12 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 src/bin/lttng-sessiond/clear.c create mode 100644 src/bin/lttng-sessiond/clear.h diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index 0ea77aadb..8b8f5ee0d 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -167,7 +167,10 @@ enum lttng_error_code { LTTNG_ERR_ROTATION_PENDING_RELAY_FAIL_CONSUMER = 144, /* Rotation pending check (relay) failure on consumer */ LTTNG_ERR_MKDIR_FAIL_CONSUMER = 145, /* mkdir failure on consumer */ 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 9800c4b2c..9d2631fc4 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -49,7 +49,8 @@ lttng_sessiond_SOURCES = utils.c utils.h \ register.c register.h \ manage-apps.c manage-apps.h \ manage-kernel.c manage-kernel.h \ - manage-consumer.c manage-consumer.h + manage-consumer.c manage-consumer.h \ + 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 80e313778..397d20725 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -1899,3 +1899,38 @@ error: health_code_update(); 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 0e7ed0017..3846d9a77 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -313,4 +313,7 @@ int consumer_mkdir(struct consumer_socket *socket, uint64_t session_id, const struct consumer_output *output, const char *path, uid_t uid, gid_t gid); +/* 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 8e972b069..aac6665be 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -1459,3 +1459,70 @@ error: rcu_read_unlock(); return status; } + +/* + * 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 9b0c15cd1..7437be556 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -64,6 +64,7 @@ enum lttng_error_code kernel_snapshot_record(struct ltt_kernel_session *ksess, 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_rotate_session(struct ltt_session *session); +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 59d8a8fc4..fb39ce12b 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -6462,3 +6462,149 @@ error: rcu_read_unlock(); return cmd_ret; } + +/* + * 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 b90ff4bce..8d6fdf037 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -356,6 +356,7 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, 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_rotate_session(struct ltt_session *session); +enum lttng_error_code ust_app_clear_session(struct ltt_session *session); static inline int ust_app_supported(void) @@ -589,6 +590,12 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) 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 dd1735dd4..c7807a013 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -208,6 +208,10 @@ static const char *error_string_array[] = { [ ERROR_INDEX(LTTNG_ERR_ROTATION_PENDING_RELAY_FAIL_CONSUMER) ] = "Rotation pending check (relay) failure on consumer", [ ERROR_INDEX(LTTNG_ERR_MKDIR_FAIL_CONSUMER) ] = "mkdir failure on consumer", [ ERROR_INDEX(LTTNG_ERR_CHAN_NOT_FOUND) ] = "Channel 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 78b94532d..336ebe978 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -170,6 +170,7 @@ enum lttcomm_return_code { LTTCOMM_CONSUMERD_ROTATION_PENDING_RELAY_FAILED, /* Rotation pending relay failed. */ LTTCOMM_CONSUMERD_MKDIR_FAILED, /* mkdir has failed. */ LTTCOMM_CONSUMERD_SNAPSHOT_FAILED, /* snapshot has failed. */ + LTTCOMM_CONSUMERD_RELAYD_DISALLOW_CLEAR, /* Relayd does not accept clear command. */ /* MUST be last element */ LTTCOMM_NR, /* Last element */ -- 2.34.1