X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=f4c7390ef784d52d9371d982e78a68dab966e358;hp=2c2ce285a676461238703f2cb77a285cdb5a66b6;hb=1831ae68b70dece8e9b847081526495adbbf05e5;hpb=7a24ece351f5be3d915e5c93201a4b9fcf1d486b diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 2c2ce285a..f4c7390ef 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1,19 +1,9 @@ /* - * Copyright (C) 2012 - David Goulet - * Copyright (C) 2016 - Jérémie Galarneau + * Copyright (C) 2012 David Goulet + * Copyright (C) 2016 Jérémie Galarneau * - * 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. + * SPDX-License-Identifier: GPL-2.0-only * - * 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 @@ -37,6 +27,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -4293,8 +4290,94 @@ end: return ret; } +/* TODO: is this the best place to perform this? (code wise) */ +/* + * Set sock to -1 if reception of more information is not necessary e.g on + * unregister. TODO find a better way. + * + * On success LTTNG_OK. On error, returns lttng_error code. + * */ +static enum lttng_error_code prepare_trigger_object(struct lttng_trigger *trigger, int sock) +{ + enum lttng_error_code ret; + /* Internal object of the trigger might have to "generate" and + * "populate" internal field e.g filter bytecode + */ + struct lttng_condition *condition = NULL; + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_EVENT_RULE_HIT: + { + struct lttng_event_rule *event_rule; + const struct lttng_credentials *credential = lttng_trigger_get_credentials(trigger); + lttng_condition_event_rule_get_rule_no_const( + condition, &event_rule); + ret = lttng_event_rule_populate(event_rule, credential->uid, credential->gid); + if (ret != LTTNG_OK) { + goto end; + } + + switch (lttng_event_rule_get_type(event_rule)) { + case LTTNG_EVENT_RULE_TYPE_UPROBE: + { + int fd; + struct lttng_userspace_probe_location *location = lttng_event_rule_uprobe_get_location_no_const(event_rule); + + if (sock < 0) { + /* Nothing to receive */ + break; + } + /* + * Receive the file descriptor to the target binary from + * the client. + */ + DBG("Receiving userspace probe target FD from client ..."); + ret = lttcomm_recv_fds_unix_sock(sock, &fd, 1); + if (ret <= 0) { + DBG("Nothing recv() from client userspace probe fd... continuing"); + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + /* + * Set the file descriptor received from the client + * through the unix socket in the probe location. + */ + ret = lttng_userspace_probe_location_set_binary_fd( + location, fd); + if (ret) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + break; + } + default: + /* Nothing to do */ + break; + } + ret = LTTNG_OK; + break; + } + default: + { + ret = LTTNG_OK; + break; + } + } +end: + return ret; +} + +/* Caller must call lttng_destroy_trigger on the returned trigger object */ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, - struct notification_thread_handle *notification_thread) + struct notification_thread_handle *notification_thread, + struct lttng_trigger **return_trigger) { int ret; size_t trigger_len; @@ -4328,9 +4411,95 @@ int cmd_register_trigger(struct command_ctx *cmd_ctx, int sock, goto end; } + /* Set the trigger credential */ + lttng_trigger_set_credentials(trigger, cmd_ctx->creds.uid, cmd_ctx->creds.gid); + + /* Prepare internal trigger object if needed on reception. + * Handles also special treatment for certain internal object of the + * trigger (e.g uprobe event rule binary fd. + */ + ret = prepare_trigger_object(trigger, sock); + if (ret != LTTNG_OK) { + goto end; + } + + /* + * Since we return the trigger object, take a reference to it + * Caller is responsible for calling lttng_destroy_trigger on it. + * This thread does not OWN the trigger. + */ + lttng_trigger_get(trigger); + + /* Inform the notification thread */ ret = notification_thread_command_register_trigger(notification_thread, trigger); - /* Ownership of trigger was transferred. */ + if (ret != LTTNG_OK) { + goto end; + } + + /* Synchronize tracers, only if needed */ + /* TODO: maybe extract somewhere else */ + { + struct lttng_condition *condition = NULL; + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + const struct lttng_event_rule *rule = NULL; + (void) lttng_condition_event_rule_get_rule(condition, &rule); + if (!rule) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + kernel_update_tokens(); + } else { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ust_app_global_update_all_tokens(); + /* Agent handling */ + if (lttng_event_rule_is_agent(rule)) { + struct agent *agt; + const char *pattern; + enum lttng_domain_type domain_type; + domain_type = lttng_event_rule_get_domain_type( + rule); + (void) lttng_event_rule_tracepoint_get_pattern( + rule, &pattern); + agt = trigger_find_agent(domain_type); + if (!agt) { + agt = agent_create(domain_type); + if (!agt) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + agent_add(agt, trigger_agents_ht_by_domain); + } + + ret = trigger_agent_enable( + trigger, agt); + if (ret != LTTNG_OK) { + goto end; + } + } + } + } + } + + /* Return an image of the updated object to the client */ + *return_trigger = trigger; + /* Ownership of trigger was transferred to caller. */ trigger = NULL; end: lttng_trigger_destroy(trigger); @@ -4373,14 +4542,110 @@ int cmd_unregister_trigger(struct command_ctx *cmd_ctx, int sock, goto end; } + lttng_trigger_set_credentials(trigger, cmd_ctx->creds.uid, cmd_ctx->creds.gid); + + /* TODO: forgotting this bited me for agent since the filter is + * genereted on this side. Wonder if we could find a way to detect when + * do it or not. + */ + + /* Prepare internal trigger object if needed on reception. + * Handles also special treatment for certain internal object of the + * trigger (e.g uprobe event rule binary fd. + */ + ret = prepare_trigger_object(trigger, -1); + if (ret != LTTNG_OK) { + goto end; + } + ret = notification_thread_command_unregister_trigger(notification_thread, trigger); + + /* Synchronize tracers, only if needed */ + /* TODO: maybe extract somewhere else */ + { + struct lttng_condition *condition = NULL; + condition = lttng_trigger_get_condition(trigger); + if (!condition) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT) { + const struct lttng_event_rule *rule = NULL; + (void) lttng_condition_event_rule_get_rule(condition, &rule); + if (!rule) { + ret = LTTNG_ERR_INVALID_TRIGGER; + goto end; + } + if (lttng_event_rule_get_domain_type(rule) == LTTNG_DOMAIN_KERNEL) { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + kernel_update_tokens(); + } else { + /* TODO: get the token value from the + * notification thread and only perform an + * enable and a disable.... This is NOT + * OPTIMIZED AT ALL + */ + ust_app_global_update_all_tokens(); + if (lttng_event_rule_is_agent(rule)) { + struct agent *agt; + const char *pattern; + enum lttng_domain_type domain_type; + + domain_type = lttng_event_rule_get_domain_type( + rule); + (void) lttng_event_rule_tracepoint_get_pattern( + rule, &pattern); + + agt = trigger_find_agent(domain_type); + if (!agt) { + ret = LTTNG_ERR_UST_EVENT_NOT_FOUND; + goto end; + } + ret = trigger_agent_disable( + trigger, agt); + if (ret != LTTNG_OK) { + goto end; + } + } + } + } + } + end: lttng_trigger_destroy(trigger); lttng_dynamic_buffer_reset(&trigger_buffer); return ret; } +int cmd_list_triggers(struct command_ctx *cmd_ctx, int sock, + struct notification_thread_handle *notification_thread, + struct lttng_triggers **return_triggers) +{ + int ret = 0; + enum lttng_error_code ret_code; + struct lttng_triggers *triggers = NULL; + + /* Get list of token trigger from the notification thread here */ + ret_code = notification_thread_command_list_triggers(notification_thread_handle, cmd_ctx->creds.uid, cmd_ctx->creds.gid, &triggers); + if (ret_code != LTTNG_OK) { + ret = ret_code; + goto end; + } + + /* Return a "view" of the current triggers */ + *return_triggers = triggers; + triggers = NULL; + ret = LTTNG_OK; +end: + lttng_triggers_destroy(triggers); + return ret; +} /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination. @@ -4584,7 +4849,7 @@ int64_t get_session_nb_packets_per_stream(const struct ltt_session *session, } cur_nb_packets++; } - if (!cur_nb_packets) { + if (!cur_nb_packets && size_left != max_size) { /* Not enough room to grab one packet of each stream, error. */ return -1; } @@ -4697,7 +4962,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, snapshot_output->max_size); if (nb_packets_per_stream < 0) { ret_code = LTTNG_ERR_MAX_SIZE_INVALID; - goto error; + goto error_close_trace_chunk; } if (session->kernel_session) { @@ -4705,7 +4970,7 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, snapshot_kernel_consumer_output, session, wait, nb_packets_per_stream); if (ret_code != LTTNG_OK) { - goto error; + goto error_close_trace_chunk; } } @@ -4714,10 +4979,11 @@ enum lttng_error_code snapshot_record(struct ltt_session *session, snapshot_ust_consumer_output, session, wait, nb_packets_per_stream); if (ret_code != LTTNG_OK) { - goto error; + goto error_close_trace_chunk; } } +error_close_trace_chunk: if (session_set_trace_chunk(session, NULL, &snapshot_trace_chunk)) { ERR("Failed to release the current trace chunk of session \"%s\"", session->name);