X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fagent.c;h=988d2c4abad8dc4e29877c069616cfa3f6d63d33;hb=65555e50c8953ae42c63a29374266aac6d2dabea;hp=1eb64c25e32b937282bd5f1b45c7442d3909b188;hpb=a0a9a2fe88ad16f3a0ac704815b8c4ded4438605;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/agent.c b/src/bin/lttng-sessiond/agent.c index 1eb64c25e..988d2c4ab 100644 --- a/src/bin/lttng-sessiond/agent.c +++ b/src/bin/lttng-sessiond/agent.c @@ -65,6 +65,7 @@ static int ht_match_event(struct cds_lfht_node *node, { struct agent_event *event; const struct agent_ht_key *key; + int ll_match; assert(node); assert(_key); @@ -79,14 +80,28 @@ static int ht_match_event(struct cds_lfht_node *node, goto no_match; } - if (event->loglevel != key->loglevel) { - if (event->loglevel_type == LTTNG_EVENT_LOGLEVEL_ALL && - key->loglevel == 0 && event->loglevel == -1) { - goto match; - } + /* Event loglevel value and type. */ + ll_match = loglevels_match(event->loglevel_type, + event->loglevel_value, key->loglevel_type, + key->loglevel_value, LTTNG_EVENT_LOGLEVEL_ALL); + + if (!ll_match) { + goto no_match; + } + + /* Filter expression */ + if (!!event->filter_expression ^ !!key->filter_expression) { + /* One has a filter expression, the other does not */ goto no_match; } -match: + + if (event->filter_expression) { + if (strncmp(event->filter_expression, key->filter_expression, + strlen(event->filter_expression)) != 0) { + goto no_match; + } + } + return 1; no_match: @@ -107,7 +122,9 @@ static void add_unique_agent_event(struct lttng_ht *ht, assert(event); key.name = event->name; - key.loglevel = event->loglevel; + key.loglevel_value = event->loglevel_value; + key.loglevel_type = event->loglevel_type; + key.filter_expression = event->filter_expression; node_ptr = cds_lfht_add_unique(ht->ht, ht->hash_fct(event->node.key, lttng_ht_seed), @@ -125,7 +142,7 @@ static void destroy_event_agent_rcu(struct rcu_head *head) struct agent_event *event = caa_container_of(node, struct agent_event, node); - free(event); + agent_destroy_event(event); } /* @@ -289,8 +306,11 @@ static ssize_t list_events(struct agent_app *app, struct lttng_event **events) for (i = 0; i < nb_event; i++) { offset += len; - strncpy(tmp_events[i].name, reply->payload + offset, - sizeof(tmp_events[i].name)); + if (lttng_strncpy(tmp_events[i].name, reply->payload + offset, + sizeof(tmp_events[i].name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } tmp_events[i].pid = app->pid; tmp_events[i].enabled = -1; len = strlen(reply->payload + offset) + 1; @@ -338,7 +358,7 @@ static int enable_event(struct agent_app *app, struct agent_event *event) } memset(&msg, 0, sizeof(msg)); - msg.loglevel = event->loglevel; + msg.loglevel_value = event->loglevel_value; msg.loglevel_type = event->loglevel_type; strncpy(msg.name, event->name, sizeof(msg.name)); ret = send_payload(app->sock, &msg, sizeof(msg)); @@ -393,14 +413,17 @@ static int disable_event(struct agent_app *app, struct agent_event *event) app->pid, app->sock->fd); data_size = sizeof(msg); + memset(&msg, 0, sizeof(msg)); + if (lttng_strncpy(msg.name, event->name, sizeof(msg.name))) { + ret = LTTNG_ERR_INVALID; + goto error; + } ret = send_header(app->sock, data_size, AGENT_CMD_DISABLE, 0); if (ret < 0) { goto error_io; } - memset(&msg, 0, sizeof(msg)); - strncpy(msg.name, event->name, sizeof(msg.name)); ret = send_payload(app->sock, &msg, sizeof(msg)); if (ret < 0) { goto error_io; @@ -494,11 +517,14 @@ error: int agent_disable_event(struct agent_event *event, enum lttng_domain_type domain) { - int ret; + int ret = LTTNG_OK; struct agent_app *app; struct lttng_ht_iter iter; assert(event); + if (!event->enabled) { + goto end; + } rcu_read_lock(); @@ -516,10 +542,10 @@ int agent_disable_event(struct agent_event *event, } event->enabled = 0; - ret = LTTNG_OK; error: rcu_read_unlock(); +end: return ret; } @@ -781,33 +807,40 @@ error: } /* - * Create a newly allocated agent event data structure. If name is valid, it's - * copied into the created event. + * Create a newly allocated agent event data structure. + * Ownership of filter_expression is taken. * * Return a new object else NULL on error. */ struct agent_event *agent_create_event(const char *name, - struct lttng_filter_bytecode *filter) + enum lttng_loglevel_type loglevel_type, int loglevel_value, + struct lttng_filter_bytecode *filter, char *filter_expression) { - struct agent_event *event; + struct agent_event *event = NULL; - DBG3("Agent create new event with name %s", name); + DBG3("Agent create new event with name %s, loglevel type %d, \ + loglevel value %d and filter %s", + name, loglevel_type, loglevel_value, + filter_expression ? filter_expression : "NULL"); - event = zmalloc(sizeof(*event)); - if (!event) { + if (!name) { + ERR("Failed to create agent event; no name provided."); goto error; } - if (name) { - strncpy(event->name, name, sizeof(event->name)); - event->name[sizeof(event->name) - 1] = '\0'; - lttng_ht_node_init_str(&event->node, event->name); + event = zmalloc(sizeof(*event)); + if (!event) { + goto error; } - if (filter) { - event->filter = filter; - } + strncpy(event->name, name, sizeof(event->name)); + event->name[sizeof(event->name) - 1] = '\0'; + lttng_ht_node_init_str(&event->node, event->name); + event->loglevel_value = loglevel_value; + event->loglevel_type = loglevel_type; + event->filter = filter; + event->filter_expression = filter_expression; error: return event; } @@ -830,51 +863,59 @@ void agent_add_event(struct agent_event *event, struct agent *agt) } /* - * Find a agent event in the given agent using name. + * Find multiple agent events sharing the given name. * - * RCU read side lock MUST be acquired. + * RCU read side lock MUST be acquired. It must be held for the + * duration of the iteration. * - * Return object if found else NULL. + * Sets the given iterator. */ -struct agent_event *agent_find_event_by_name(const char *name, - struct agent *agt) +void agent_find_events_by_name(const char *name, struct agent *agt, + struct lttng_ht_iter* iter) { - struct lttng_ht_node_str *node; - struct lttng_ht_iter iter; struct lttng_ht *ht; struct agent_ht_key key; assert(name); assert(agt); assert(agt->events); + assert(iter); ht = agt->events; key.name = name; cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), - ht_match_event_by_name, &key, &iter.iter); - node = lttng_ht_iter_get_node_str(&iter); - if (node == NULL) { - goto error; - } + ht_match_event_by_name, &key, &iter->iter); +} - DBG3("Agent event found %s by name.", name); - return caa_container_of(node, struct agent_event, node); +/* + * Get the next agent event duplicate by name. This should be called + * after a call to agent_find_events_by_name() to iterate on events. + * + * The RCU read lock must be held during the iteration and for as long + * as the object the iterator points to remains in use. + */ +void agent_event_next_duplicate(const char *name, + struct agent *agt, struct lttng_ht_iter* iter) +{ + struct agent_ht_key key; -error: - DBG3("Agent NOT found by name %s.", name); - return NULL; + key.name = name; + + cds_lfht_next_duplicate(agt->events->ht, ht_match_event_by_name, + &key, &iter->iter); } /* - * Find a agent event in the given agent using name and loglevel. + * Find a agent event in the given agent using name, loglevel and filter. * * RCU read side lock MUST be acquired. * * Return object if found else NULL. */ -struct agent_event *agent_find_event(const char *name, int loglevel, - struct agent *agt) +struct agent_event *agent_find_event(const char *name, + enum lttng_loglevel_type loglevel_type, int loglevel_value, + char *filter_expression, struct agent *agt) { struct lttng_ht_node_str *node; struct lttng_ht_iter iter; @@ -887,7 +928,9 @@ struct agent_event *agent_find_event(const char *name, int loglevel, ht = agt->events; key.name = name; - key.loglevel = loglevel; + key.loglevel_value = loglevel_value; + key.loglevel_type = loglevel_type; + key.filter_expression = filter_expression; cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), ht_match_event, &key, &iter.iter); @@ -914,12 +957,13 @@ void agent_destroy_event(struct agent_event *event) assert(event); free(event->filter); + free(event->filter_expression); + free(event->exclusion); free(event); } /* - * Destroy an agent completely. Note that the given pointer is NOT freed - * thus a reference to static or stack data can be passed to this function. + * Destroy an agent completely. */ void agent_destroy(struct agent *agt) { @@ -958,19 +1002,71 @@ void agent_destroy(struct agent *agt) rcu_read_unlock(); ht_cleanup_push(agt->events); + free(agt); } /* - * Initialize agent subsystem. + * Allocate agent_apps_ht_by_sock. */ -int agent_setup(void) +int agent_app_ht_alloc(void) { + int ret = 0; + agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); if (!agent_apps_ht_by_sock) { - return -1; + ret = -1; } - return 0; + return ret; +} + +/* + * Destroy a agent application by socket. + */ +void agent_destroy_app_by_sock(int sock) +{ + struct agent_app *app; + + assert(sock >= 0); + + /* + * Not finding an application is a very important error that should NEVER + * happen. The hash table deletion is ONLY done through this call when the + * main sessiond thread is torn down. + */ + rcu_read_lock(); + app = agent_find_app_by_sock(sock); + assert(app); + + /* RCU read side lock is assumed to be held by this function. */ + agent_delete_app(app); + + /* The application is freed in a RCU call but the socket is closed here. */ + agent_destroy_app(app); + rcu_read_unlock(); +} + +/* + * Clean-up the agent app hash table and destroy it. + */ +void agent_app_ht_clean(void) +{ + struct lttng_ht_node_ulong *node; + struct lttng_ht_iter iter; + + if (!agent_apps_ht_by_sock) { + return; + } + rcu_read_lock(); + cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) { + struct agent_app *app; + + app = caa_container_of(node, struct agent_app, node); + agent_destroy_app_by_sock(app->sock->fd); + } + rcu_read_unlock(); + + lttng_ht_destroy(agent_apps_ht_by_sock); } /*