X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=67ac9fd7bd7c2cfe3313c57ecdf54d624f383e00;hp=a2af8882f289397b55f889f6f6995566b02aa3f6;hb=refs%2Fheads%2Fsow-2020-0002-rev2;hpb=11f6ce94d8fb73f017888681aaba5d7df55fc735 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index a2af8882f..67ac9fd7b 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -30,13 +31,19 @@ #include #include #include -#include -#include +#include +#include #include #include #include +#include +#include +#include #include #include +#include "lttng/domain.h" +#include "lttng/map/map.h" +#include #include #include #include @@ -57,12 +64,14 @@ #include "lttng-syscall.h" #include "agent.h" #include "buffer-registry.h" +#include "map.h" #include "notification-thread.h" #include "notification-thread-commands.h" #include "rotate.h" #include "rotation-thread.h" #include "timer.h" #include "agent-thread.h" +#include "session.h" #include "tracker.h" #include "cmd.h" @@ -288,6 +297,340 @@ end: return ret; } +enum tracer_executed_action_state { + TRACER_EXECUTED_ACTION_STATE_REGISTER, + TRACER_EXECUTED_ACTION_STATE_UNREGISTER +}; + +static +enum lttng_error_code sync_incr_value_action_ust( + struct ltt_session *session, + const struct lttng_condition *condition, + const char *map_name, + uint64_t tracer_token, + struct lttng_map_key *key, + enum tracer_executed_action_state state) +{ + enum lttng_error_code ret_code; + const struct lttng_event_rule *event_rule; + enum lttng_condition_status cond_status; + enum lttng_event_rule_status er_status; + struct ltt_ust_session *usess = session->ust_session; + const char *pattern; + struct ltt_ust_map *map; + char *filter_expression; + struct lttng_bytecode *filter; + struct lttng_event_exclusion *exclusion; + enum lttng_event_rule_generate_exclusions_status + generate_exclusion_status; + + DBG("Syncing UST incr-value action for session '%s', map '%s'", + session->name, map_name); + if (!usess) { + DBG("No UST session"); + ret_code = LTTNG_OK; + goto end; + } + + assert(usess->domain_global.maps); + + map = trace_ust_find_map_by_name(usess->domain_global.maps, map_name); + if (!map) { + DBG("UST map \"%s\" not found", map_name); + ret_code = LTTNG_OK; + goto end; + } + + cond_status = lttng_condition_on_event_get_rule(condition, &event_rule); + if (cond_status != LTTNG_CONDITION_STATUS_OK) { + ERR("Error getting on-event condition event-rule"); + ret_code = LTTNG_ERR_INVALID_MAP; + goto end; + } + + er_status = lttng_event_rule_tracepoint_get_pattern(event_rule, &pattern); + if (er_status != LTTNG_EVENT_RULE_STATUS_OK) { + /* At this point, this is a fatal error. */ + abort(); + } + + /* + * FIXME: frdeso, reuse the event notifier functions and approach to + * create the event. + */ + filter_expression = (char *) lttng_event_rule_get_filter(event_rule); + filter = (struct lttng_bytecode *)lttng_event_rule_get_filter_bytecode( + event_rule); + generate_exclusion_status = lttng_event_rule_generate_exclusions( + event_rule, &exclusion); + if (generate_exclusion_status == LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR) { + ERR("Error generating the exclusion"); + ret_code = LTTNG_ERR_EXCLUSION_INVAL; + goto end; + } + + switch (state) { + case TRACER_EXECUTED_ACTION_STATE_REGISTER: + ret_code = map_event_ust_enable_tracepoint(usess, + map, tracer_token, (char *) pattern, key, + LTTNG_EVENT_TRACEPOINT, LTTNG_EVENT_LOGLEVEL_ALL, + 0, filter_expression, filter, exclusion, false); + if (ret_code == LTTNG_ERR_UST_EVENT_ENABLED) { + ret_code = LTTNG_OK; + } else if (ret_code != LTTNG_OK) { + ERR("Enabling UST map event"); + goto end; + } + break; + case TRACER_EXECUTED_ACTION_STATE_UNREGISTER: + ret_code = map_event_ust_disable_tracepoint(usess, + map, tracer_token, (char *) pattern, key, + LTTNG_EVENT_TRACEPOINT, LTTNG_EVENT_LOGLEVEL_ALL, + 0, filter_expression, filter, exclusion, false); + if (ret_code == LTTNG_ERR_UST_EVENT_ENABLED) { + ret_code = LTTNG_OK; + } else if (ret_code != LTTNG_OK) { + ERR("Enabling UST map event"); + goto end; + } + break; + default: + abort(); + } + + ret_code = LTTNG_OK; + +end: + return ret_code; +} + +static +enum lttng_error_code sync_incr_value_action_kernel( + struct ltt_session *session, + const struct lttng_credentials *creds, + const struct lttng_condition *condition, + const char *map_name, + uint64_t tracer_token, + struct lttng_map_key *key, + enum tracer_executed_action_state state) +{ + enum lttng_error_code ret_code; + const struct lttng_event_rule *event_rule; + enum lttng_condition_status cond_status; + struct ltt_kernel_map *kmap; + struct ltt_kernel_session *ksess = session->kernel_session; + + DBG("Syncing kernel incr-value action for session '%s', map '%s'", + session->name, map_name); + + if (!ksess) { + DBG("No kernel session"); + ret_code = LTTNG_OK; + goto end; + } + + kmap = trace_kernel_get_map_by_name(map_name, ksess); + if (!kmap) { + DBG("Kernel map \"%s\" not found", map_name); + ret_code = LTTNG_OK; + goto end; + } + + cond_status = lttng_condition_on_event_get_rule(condition, &event_rule); + if (cond_status != LTTNG_CONDITION_STATUS_OK) { + ret_code = LTTNG_ERR_INVALID_MAP; + ERR("Error getting on-event condition event-rule"); + goto end; + } + + switch (state) { + case TRACER_EXECUTED_ACTION_STATE_REGISTER: + ret_code = map_event_kernel_enable_event(kmap, creds, tracer_token, + event_rule, key); + if(ret_code != LTTNG_OK) { + ERR("Error enabling event counter to the kernel tracer"); + goto end; + } + break; + case TRACER_EXECUTED_ACTION_STATE_UNREGISTER: + ret_code = map_event_kernel_disable_event(kmap, tracer_token); + if(ret_code != LTTNG_OK) { + ERR("Error disabling event counter to the kernel tracer"); + goto end; + } + break; + } + +end: + return ret_code; +} + +static +enum lttng_error_code sync_incr_value_action( + const struct lttng_credentials *creds, + const struct lttng_condition *condition, + const struct lttng_action *action, + enum tracer_executed_action_state state) +{ + enum lttng_error_code ret; + const char *session_name, *map_name; + enum lttng_action_status action_status; + enum lttng_condition_status cond_status; + const struct lttng_event_rule *event_rule; + struct ltt_session *session = NULL; + struct lttng_map_key *key; + uint64_t action_tracer_token; + + action_status = lttng_action_incr_value_get_map_name(action, + &map_name); + if (action_status != LTTNG_ACTION_STATUS_OK) { + ERR("Map name not set for incr-value action"); + ret = LTTNG_ERR_INVALID_MAP; + goto end; + } + + action_status = lttng_action_incr_value_get_session_name(action, + &session_name); + if (action_status != LTTNG_ACTION_STATUS_OK) { + ERR("Session name not set for incr-value action"); + ret = LTTNG_ERR_INVALID_MAP; + goto end; + } + + action_status = lttng_action_incr_value_borrow_key_mutable(action, &key); + if (action_status != LTTNG_ACTION_STATUS_OK) { + ERR("Key not set for incr-value action"); + ret = LTTNG_ERR_INVALID_MAP; + goto end; + } + + /* Returns a refcounted reference */ + session = session_find_by_name(session_name); + if(!session) { + DBG("Session not found for incr-value action: session-name=%s", + session_name); + ret = LTTNG_OK; + goto end; + } + + cond_status = lttng_condition_on_event_get_rule(condition, &event_rule); + if (cond_status != LTTNG_CONDITION_STATUS_OK) { + ERR("Error getting on-event condition event-rule"); + ret = LTTNG_ERR_INVALID_MAP; + session_put(session); + goto end; + } + + action_tracer_token = lttng_action_incr_value_get_tracer_token(action); + + switch (lttng_event_rule_get_domain_type(event_rule)) { + case LTTNG_DOMAIN_UST: + ret = sync_incr_value_action_ust(session, condition, + map_name, action_tracer_token, key, state); + if (ret == LTTNG_ERR_UST_EVENT_EXIST) { + DBG("Incr-value action already registered"); + ret = LTTNG_OK; + } + break; + case LTTNG_DOMAIN_KERNEL: + ret = sync_incr_value_action_kernel(session, creds, condition, + map_name, action_tracer_token, key, state); + if (ret == LTTNG_ERR_KERN_EVENT_EXIST) { + DBG("Incr-value action already registered"); + ret = LTTNG_OK; + } + break; + default: + abort(); + } + + goto end; +end: + if (session) { + session_put(session); + } + return ret; +} + +static +enum lttng_error_code sync_one_tracer_executed_action( + const struct lttng_credentials *creds, + const struct lttng_condition *condition, + const struct lttng_action *action, + enum tracer_executed_action_state state) +{ + enum lttng_action_type action_type; + enum lttng_error_code ret; + + action_type = lttng_action_get_type(action); + assert(action_type != LTTNG_ACTION_TYPE_GROUP); + + switch (action_type) { + case LTTNG_ACTION_TYPE_INCREMENT_VALUE: + DBG("Action type \"%s\" is a tracer executed action.", + lttng_action_type_string(action_type)); + + ret = sync_incr_value_action(creds, condition, action, state); + if (ret != LTTNG_OK) { + ERR("Error syncing increment value action to the tracer"); + } + break; + default: + DBG("Action type \"%s\" is not a tracer executed action.", + lttng_action_type_string(action_type)); + ret = LTTNG_OK; + goto end; + } + +end: + return ret; +} + +static +enum lttng_error_code sync_all_tracer_executed_actions( + const struct lttng_trigger *trigger, + const struct lttng_credentials *cmd_creds, + enum tracer_executed_action_state state) +{ + enum lttng_error_code ret; + unsigned int i, count; + enum lttng_action_status action_status; + enum lttng_action_type action_type; + const struct lttng_action *action; + const struct lttng_condition *condition; + + condition = lttng_trigger_get_const_condition(trigger); + action = lttng_trigger_get_const_action(trigger); + + action_type = lttng_action_get_type(action); + + DBG("Iterating over all actions of trigger \"%s\" to sync any tracer executed actions", + trigger->name); + + if (action_type != LTTNG_ACTION_TYPE_GROUP) { + ret = sync_one_tracer_executed_action(cmd_creds, condition, action, + state); + } else { + action_status = lttng_action_group_get_count(action, &count); + assert(action_status == LTTNG_ACTION_STATUS_OK); + + for (i = 0; i < count; i++) { + const struct lttng_action *inner_action = + lttng_action_group_get_at_index(action, i); + + ret = sync_one_tracer_executed_action(cmd_creds, condition, + inner_action, state); + if (ret != LTTNG_OK) { + ERR("Error syncing tracer executed action"); + goto end; + } + } + } + +end: + return ret; +} + /* * Fill lttng_channel array of all channels. */ @@ -1523,6 +1866,237 @@ end: return ret; } +enum lttng_error_code cmd_add_map(struct command_ctx *cmd_ctx, int sock) +{ + int ret; + enum lttng_error_code ret_code; + size_t map_len; + struct lttng_payload map_payload; + ssize_t sock_recv_len; + struct lttng_map *map = NULL; + const struct lttng_credentials cmd_creds = { + .uid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.uid), + .gid = LTTNG_OPTIONAL_INIT_VALUE(cmd_ctx->creds.gid), + }; + + lttng_payload_init(&map_payload); + map_len = (size_t) cmd_ctx->lsm.u.add_map.length; + ret = lttng_dynamic_buffer_set_size( + &map_payload.buffer, map_len); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + sock_recv_len = lttcomm_recv_unix_sock( + sock, map_payload.buffer.data, map_len); + if (sock_recv_len < 0 || sock_recv_len != map_len) { + ERR("Failed to receive \"register map\" command payload"); + ret_code = LTTNG_ERR_INVALID_MAP; + goto end; + } + + /* Deserialize map. */ + { + struct lttng_payload_view view = + lttng_payload_view_from_payload( + &map_payload, 0, -1); + + if (lttng_map_create_from_payload(&view, &map) != map_len) { + ERR("Invalid map payload received in \"add map\" command"); + ret_code = LTTNG_ERR_INVALID_MAP; + goto end; + } + } + + switch (lttng_map_get_domain(map)) { + case LTTNG_DOMAIN_KERNEL: + ret_code = map_kernel_add(cmd_ctx->session->kernel_session, map); + if (ret_code != LTTNG_OK) { + ERR("Creating a new kernel map: %s", lttng_strerror(ret_code)); + goto end; + } + + ret_code = LTTNG_OK; + break; + case LTTNG_DOMAIN_UST: + ret = map_ust_add(cmd_ctx->session->ust_session, map); + if (ret) { + ERR("Creating a new UST map: %s", lttng_strerror(-ret)); + ret_code = ret; + goto end; + } + + ret_code = LTTNG_OK; + break; + default: + abort(); + } + + + { + struct lttng_triggers *triggers = NULL; + enum lttng_trigger_status t_status; + unsigned int count, i; + + /* + * FRDESO: beware of moving this code. This is currently not + * racy because this is executed by the client thread and the + * client thread is the thread registering new triggers. If + * this code is relocate special care must be taken. + */ + ret_code = notification_thread_command_list_triggers( + notification_thread_handle, 0, &triggers); + if (ret_code != LTTNG_OK) { + ret = -1; + goto end; + } + + assert(triggers); + + t_status = lttng_triggers_get_count(triggers, &count); + if (t_status != LTTNG_TRIGGER_STATUS_OK) { + ret = -1; + lttng_triggers_destroy(triggers); + goto end; + } + + for (i = 0; i < count; i++) { + const struct lttng_trigger *trigger; + + trigger = lttng_triggers_get_at_index(triggers, i); + assert(trigger); + + ret_code = sync_all_tracer_executed_actions(trigger, + &cmd_creds, TRACER_EXECUTED_ACTION_STATE_REGISTER); + assert(ret_code == LTTNG_OK); + } + + lttng_triggers_destroy(triggers); + } + + lttng_map_put(map); + +end: + lttng_payload_reset(&map_payload); + return ret_code; +} + +enum lttng_error_code cmd_enable_map(struct ltt_session *session, + enum lttng_domain_type domain, char *map_name) +{ + struct ltt_ust_session *usess = session->ust_session; + enum lttng_error_code ret_code; + + DBG("Enabling map %s for session %s", map_name, session->name); + + rcu_read_lock(); + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_map *kmap; + struct ltt_kernel_session *ksess = session->kernel_session; + + kmap = trace_kernel_get_map_by_name(map_name, ksess); + if (kmap == NULL) { + ret_code = LTTNG_ERR_KERNEL_MAP_NOT_FOUND; + goto error; + } + + ret_code = map_kernel_enable(ksess, kmap); + if (ret_code != LTTNG_OK) { + goto error; + } + break; + } + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_map *umap; + struct lttng_ht *map_ht; + + map_ht = usess->domain_global.maps; + + umap = trace_ust_find_map_by_name(map_ht, map_name); + if (umap == NULL) { + ret_code = LTTNG_ERR_UST_MAP_NOT_FOUND; + goto error; + } + + ret_code = map_ust_enable(usess, umap); + if (ret_code != LTTNG_OK) { + goto error; + } + break; + } + default: + abort(); + } + + ret_code = LTTNG_OK; +error: + rcu_read_unlock(); + return ret_code; +} + +enum lttng_error_code cmd_disable_map(struct ltt_session *session, + enum lttng_domain_type domain, char *map_name) +{ + enum lttng_error_code ret_code; + + rcu_read_lock(); + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_map *kmap; + struct ltt_kernel_session *ksess = session->kernel_session; + + kmap = trace_kernel_get_map_by_name(map_name, ksess); + if (kmap == NULL) { + ret_code = LTTNG_ERR_KERNEL_MAP_NOT_FOUND; + goto error; + } + + ret_code = map_kernel_disable(ksess, kmap); + if (ret_code != LTTNG_OK) { + goto error; + } + break; + } + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_map *umap; + struct lttng_ht *map_ht; + struct ltt_ust_session *usess = session->ust_session; + + assert(usess); + + map_ht = usess->domain_global.maps; + + umap = trace_ust_find_map_by_name(map_ht, map_name); + if (umap == NULL) { + ret_code = LTTNG_ERR_UST_MAP_NOT_FOUND; + goto error; + } + + ret_code = map_ust_disable(usess, umap); + if (ret_code != LTTNG_OK) { + goto error; + } + break; + } + default: + abort(); + } + + ret_code = LTTNG_OK; + +error: + rcu_read_unlock(); + return ret_code; +} + enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( struct ltt_session *session, enum lttng_domain_type domain, @@ -2594,7 +3168,7 @@ ssize_t cmd_list_syscalls(struct lttng_event **events) int cmd_start_trace(struct ltt_session *session) { enum lttng_error_code ret; - unsigned long nb_chan = 0; + unsigned long nb_chan = 0, nb_map = 0; struct ltt_kernel_session *ksession; struct ltt_ust_session *usess; const bool session_rotated_after_last_stop = @@ -2637,11 +3211,13 @@ int cmd_start_trace(struct ltt_session *session) */ if (usess && usess->domain_global.channels) { nb_chan += lttng_ht_get_count(usess->domain_global.channels); + nb_map += lttng_ht_get_count(usess->domain_global.maps); } if (ksession) { nb_chan += ksession->channel_count; + nb_map += ksession->map_count; } - if (!nb_chan) { + if (!nb_chan && !nb_map) { ret = LTTNG_ERR_NO_CHANNEL; goto error; } @@ -3653,6 +4229,64 @@ end: return ret; } +enum lttng_error_code cmd_list_maps(enum lttng_domain_type domain, + struct ltt_session *session, + struct lttng_map_list **return_map_list) +{ + enum lttng_error_code ret_code; + struct lttng_map_list *map_list = NULL; + + map_list = lttng_map_list_create(); + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (session->kernel_session != NULL) { + struct ltt_kernel_map *kmap; + cds_list_for_each_entry(kmap, + &session->kernel_session->map_list.head, list) { + enum lttng_map_status map_status; + map_status = lttng_map_list_add(map_list, kmap->map); + if (map_status != LTTNG_MAP_STATUS_OK) { + ERR("Error appending kernel map to list"); + ret_code = LTTNG_ERR_FATAL; + break; + } + } + + } + break; + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_map *umap; + struct lttng_ht_iter iter; + + rcu_read_lock(); + cds_lfht_for_each_entry(session->ust_session->domain_global.maps->ht, + &iter.iter, umap, node.node) { + enum lttng_map_status map_status; + map_status = lttng_map_list_add(map_list, umap->map); + if (map_status != LTTNG_MAP_STATUS_OK) { + ERR("Error appending UST map to list"); + ret_code = LTTNG_ERR_FATAL; + break; + } + } + rcu_read_unlock(); + break; + } + default: + ret_code = LTTNG_ERR_UND; + goto end; + } + + *return_map_list = map_list; + map_list = NULL; + ret_code = LTTNG_OK; +end: + lttng_map_list_destroy(map_list); + return ret_code; +} + /* * Command LTTNG_LIST_EVENTS processed by the client thread. */ @@ -4293,21 +4927,82 @@ end: return ret; } -static enum lttng_error_code trigger_modifies_event_notifier( - const struct lttng_trigger *trigger, bool *adds_event_notifier) +static +enum lttng_error_code synchronize_tracer_notifier_register( + struct notification_thread_handle *notification_thread, + struct lttng_trigger *trigger, const struct lttng_credentials *cmd_creds) { - enum lttng_error_code ret_code = LTTNG_OK; - const struct lttng_condition *condition = NULL; + enum lttng_error_code ret_code; + struct lttng_condition *condition = lttng_trigger_get_condition(trigger); + const char *trigger_name; + uid_t trigger_owner; + enum lttng_trigger_status trigger_status; + const enum lttng_domain_type trigger_domain = + lttng_trigger_get_underlying_domain_type_restriction( + trigger); - condition = lttng_trigger_get_const_condition(trigger); - if (!condition) { - ret_code = LTTNG_ERR_INVALID_TRIGGER; - goto end; + trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_owner); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + assert(condition); + assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT); + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? trigger_name : "(unnamed)"; + + session_lock_list(); + switch (trigger_domain) { + case LTTNG_DOMAIN_KERNEL: + { + ret_code = kernel_register_event_notifier(trigger, cmd_creds); + if (ret_code != LTTNG_OK) { + enum lttng_error_code notif_thread_unregister_ret; + + notif_thread_unregister_ret = + notification_thread_command_unregister_trigger( + notification_thread, trigger); + + if (notif_thread_unregister_ret != LTTNG_OK) { + /* Return the original error code. */ + ERR("Failed to unregister trigger from notification thread during error recovery: trigger name = '%s', trigger owner uid = %d, error code = %d", + trigger_name, + (int) trigger_owner, + ret_code); + } + } + break; + } + case LTTNG_DOMAIN_UST: + ust_app_global_update_all_event_notifier_rules(); + break; + case LTTNG_DOMAIN_NONE: + abort(); + default: + { + /* Agent domains. */ + struct agent *agt = agent_find_by_event_notifier_domain( + trigger_domain); + if (!agt) { + agt = agent_create(trigger_domain); + if (!agt) { + ret_code = LTTNG_ERR_NOMEM; + goto end_unlock_session_list; + } + agent_add(agt, trigger_agents_ht_by_domain); + } + + ret_code = trigger_agent_enable(trigger, agt); + if (ret_code != LTTNG_OK) { + goto end_unlock_session_list; + } + + break; + } } - *adds_event_notifier = lttng_condition_get_type(condition) == - LTTNG_CONDITION_TYPE_EVENT_RULE_HIT; -end: + ret_code = LTTNG_OK; +end_unlock_session_list: + session_unlock_list(); return ret_code; } @@ -4317,8 +5012,8 @@ enum lttng_error_code cmd_register_trigger(const struct lttng_credentials *cmd_c struct lttng_trigger **return_trigger) { enum lttng_error_code ret_code; - bool must_update_event_notifiers; const char *trigger_name; + const struct lttng_condition *condition; uid_t trigger_owner; enum lttng_trigger_status trigger_status; @@ -4334,7 +5029,7 @@ enum lttng_error_code cmd_register_trigger(const struct lttng_credentials *cmd_c trigger_name, (int) trigger_owner, (int) lttng_credentials_get_uid(cmd_creds)); - /* +/* * Validate the trigger credentials against the command credentials. * Only the root user can register a trigger with non-matching * credentials. @@ -4384,72 +5079,30 @@ enum lttng_error_code cmd_register_trigger(const struct lttng_credentials *cmd_c trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? trigger_name : "(unnamed)"; - ret_code = trigger_modifies_event_notifier(trigger, &must_update_event_notifiers); - if (ret_code != LTTNG_OK) { - ERR("Failed to determine if event modifies event notifiers: trigger name = '%s', trigger owner uid = %d, error code = %d", - trigger_name, (int) trigger_owner, ret_code); - goto end; - } - /* * Synchronize tracers if the trigger adds an event notifier. */ - if (must_update_event_notifiers) { - const enum lttng_domain_type trigger_domain = - lttng_trigger_get_underlying_domain_type_restriction(trigger); - - session_lock_list(); - switch (trigger_domain) { - case LTTNG_DOMAIN_KERNEL: - { - ret_code = kernel_register_event_notifier( - trigger, cmd_creds); - if (ret_code != LTTNG_OK) { - const enum lttng_error_code notif_thread_unregister_ret = - notification_thread_command_unregister_trigger( - notification_thread, - trigger); - - if (notif_thread_unregister_ret != LTTNG_OK) { - /* Return the original error code. */ - ERR("Failed to unregister trigger from notification thread during error recovery: trigger name = '%s', trigger owner uid = %d, error code = %d", - trigger_name, - (int) trigger_owner, - ret_code); - } - } - break; + if (lttng_trigger_needs_tracer_notifier(trigger)) { + ret_code = synchronize_tracer_notifier_register(notification_thread, + trigger, cmd_creds); + if (ret_code != LTTNG_OK) { + ERR("Error registering tracer notifier"); + goto end; } - case LTTNG_DOMAIN_UST: - ust_app_global_update_all_event_notifier_rules(); - break; - case LTTNG_DOMAIN_NONE: - abort(); - default: - { - /* Agent domains. */ - struct agent *agt = agent_find_by_event_notifier_domain( - trigger_domain); - - if (!agt) { - agt = agent_create(trigger_domain); - if (!agt) { - ret_code = LTTNG_ERR_NOMEM; - goto end_unlock_session_list; - } - agent_add(agt, trigger_agents_ht_by_domain); - } - - ret_code = trigger_agent_enable(trigger, agt); - if (ret_code != LTTNG_OK) { - goto end_unlock_session_list; - } + } - break; - } - } + condition = lttng_trigger_get_const_condition(trigger); + /* TODO: Extract condition below to lttng_trigger internal function */ + if (lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT) { + session_lock_list(); + ret_code = sync_all_tracer_executed_actions(trigger, + cmd_creds, TRACER_EXECUTED_ACTION_STATE_REGISTER); session_unlock_list(); + if (ret_code != LTTNG_OK) { + ERR("Error registering tracer executed actions"); + goto end; + } } /* @@ -4467,6 +5120,57 @@ enum lttng_error_code cmd_register_trigger(const struct lttng_credentials *cmd_c } end: return ret_code; +} + +static +enum lttng_error_code synchronize_tracer_notifier_unregister( + const struct lttng_trigger *trigger) +{ + enum lttng_error_code ret_code; + const struct lttng_condition *condition = + lttng_trigger_get_const_condition(trigger); + const enum lttng_domain_type trigger_domain = + lttng_trigger_get_underlying_domain_type_restriction( + trigger); + + assert(condition); + assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT); + + session_lock_list(); + switch (trigger_domain) { + case LTTNG_DOMAIN_KERNEL: + ret_code = kernel_unregister_event_notifier(trigger); + break; + case LTTNG_DOMAIN_UST: + ust_app_global_update_all_event_notifier_rules(); + break; + case LTTNG_DOMAIN_NONE: + abort(); + default: + { + /* Agent domains. */ + struct agent *agt = agent_find_by_event_notifier_domain( + trigger_domain); + if (!agt) { + agt = agent_create(trigger_domain); + if (!agt) { + ret_code = LTTNG_ERR_NOMEM; + goto end_unlock_session_list; + } + agent_add(agt, trigger_agents_ht_by_domain); + } + + ret_code = trigger_agent_disable(trigger, agt); + if (ret_code != LTTNG_OK) { + goto end_unlock_session_list; + } + + break; + } + } + + ret_code = LTTNG_OK; + end_unlock_session_list: session_unlock_list(); return ret_code; @@ -4477,15 +5181,14 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd struct notification_thread_handle *notification_thread) { enum lttng_error_code ret_code; - bool must_update_event_notifiers; const char *trigger_name; + struct lttng_trigger *real_trigger; uid_t trigger_owner; enum lttng_trigger_status trigger_status; trigger_status = lttng_trigger_get_name(trigger, &trigger_name); trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? trigger_name : "(unnamed)"; - trigger_status = lttng_trigger_get_owner_uid( - trigger, &trigger_owner); + trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_owner); assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); DBG("Running unregister trigger command: trigger name = '%s', trigger owner uid = %d, command creds uid = %d", @@ -4509,18 +5212,20 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd } } - ret_code = trigger_modifies_event_notifier(trigger, &must_update_event_notifiers); + ret_code = notification_thread_command_get_trigger( + notification_thread, trigger, &real_trigger); if (ret_code != LTTNG_OK) { - ERR("Failed to determine if event modifies event notifiers: trigger name = '%s', trigger owner uid = %d, error code = %d", + DBG("Failed to get the real trigger from notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d", trigger_name, (int) trigger_owner, ret_code); goto end; } - ret_code = notification_thread_command_unregister_trigger(notification_thread, - trigger); + ret_code = notification_thread_command_unregister_trigger( + notification_thread, real_trigger); if (ret_code != LTTNG_OK) { DBG("Failed to unregister trigger from notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d", trigger_name, (int) trigger_owner, ret_code); + goto end; } /* @@ -4529,56 +5234,28 @@ enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd * the tracers from producing notifications associated with this * event notifier. */ - if (must_update_event_notifiers) { - const enum lttng_domain_type trigger_domain = - lttng_trigger_get_underlying_domain_type_restriction( - trigger); - - session_lock_list(); - switch (trigger_domain) { - case LTTNG_DOMAIN_KERNEL: - { - ret_code = kernel_unregister_event_notifier( - trigger); - break; + if (lttng_trigger_needs_tracer_notifier(real_trigger)) { + ret_code = synchronize_tracer_notifier_unregister(real_trigger); + if (ret_code != LTTNG_OK) { + ERR("Error unregistering trigger to tracer."); + goto end; } - case LTTNG_DOMAIN_UST: - ust_app_global_update_all_event_notifier_rules(); - break; - case LTTNG_DOMAIN_NONE: - abort(); - default: - { - /* Agent domains. */ - struct agent *agt = agent_find_by_event_notifier_domain( - trigger_domain); - - if (!agt) { - agt = agent_create(trigger_domain); - if (!agt) { - ret_code = LTTNG_ERR_NOMEM; - goto end_unlock_session_list; - } - agent_add(agt, trigger_agents_ht_by_domain); - } - - ret_code = trigger_agent_disable(trigger, agt); - if (ret_code != LTTNG_OK) { - goto end_unlock_session_list; - } - break; - } - } + } - session_unlock_list(); + session_lock_list(); + ret_code = sync_all_tracer_executed_actions(real_trigger, + cmd_creds, TRACER_EXECUTED_ACTION_STATE_UNREGISTER); + session_unlock_list(); + if (ret_code != LTTNG_OK) { + ERR("Error registering tracer executed actions"); + goto end; } + lttng_trigger_put(real_trigger); end: return ret_code; -end_unlock_session_list: - session_unlock_list(); - return ret_code;} +} int cmd_list_triggers(struct command_ctx *cmd_ctx, struct notification_thread_handle *notification_thread, @@ -4603,6 +5280,76 @@ end: lttng_triggers_destroy(triggers); return ret; } + +int cmd_list_map_values(const char *session_name, + const struct lttng_map *map, + const struct lttng_map_query *map_query, + struct lttng_map_content **return_map_content) +{ + enum lttng_error_code ret; + struct ltt_session *session; + enum lttng_domain_type domain; + const char *map_name; + enum lttng_map_status map_status; + + /* Returns a refcounted reference */ + session = session_find_by_name(session_name); + if (!session) { + DBG("Session '%s' not found", session_name); + ret = LTTNG_ERR_SESS_NOT_FOUND; + goto end; + } + + domain = lttng_map_get_domain(map); + + map_status = lttng_map_get_name(map, &map_name); + assert(map_status == LTTNG_MAP_STATUS_OK); + + if (domain == LTTNG_DOMAIN_KERNEL) { + if (session->kernel_session) { + struct ltt_kernel_map *kmap; + + kmap = trace_kernel_get_map_by_name(map_name, + session->kernel_session); + if (kmap) { + ret = kernel_list_map_values(kmap, map_query, + return_map_content); + if (ret != LTTNG_OK) { + ERR("Error listing kernel map '%s' values", map_name); + goto end; + } + } else { + DBG("No kernel map '%s' in session '%s'", map_name, session_name); + } + } + } else if (domain == LTTNG_DOMAIN_UST) { + if (session->ust_session) { + struct ltt_ust_map *umap; + struct ltt_ust_session *usess = session->ust_session; + + umap = trace_ust_find_map_by_name( + usess->domain_global.maps, map_name); + if (umap) { + ret = ust_app_map_list_values(usess, umap, + map_query, return_map_content); + if (ret) { + ret = LTTNG_ERR_MAP_VALUES_LIST_FAIL; + ERR("Error listing UST map '%s' values", map_name); + goto end; + } + } else { + DBG("No UST map '%s' in session '%s'", map_name, session_name); + } + } + } + + + ret = LTTNG_OK; +end: + session_put(session); + return ret; +} + /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination.