X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Ftrace-ust.c;h=e912c53c7e0face7ca1720752f45dc36b709e777;hp=cf1642a6e9163a75f3ce9c4c7c478476304486ec;hb=1316184615e422526ef4fae68f980443414969c1;hpb=3bd1e0819b577ffcb44acd7c2f8e02ff09654b7b diff --git a/ltt-sessiond/trace-ust.c b/ltt-sessiond/trace-ust.c index cf1642a6e..e912c53c7 100644 --- a/ltt-sessiond/trace-ust.c +++ b/ltt-sessiond/trace-ust.c @@ -24,78 +24,55 @@ #include #include +#include "hashtable.h" #include "trace-ust.h" /* - * Using a ust session list, it will return the session corresponding to the - * pid. Must be a session of domain LTTNG_DOMAIN_UST_PID. + * Find the channel in the hashtable. */ -struct ltt_ust_session *trace_ust_get_session_by_pid( - struct ltt_ust_session_list *session_list, pid_t pid) +struct ltt_ust_channel *trace_ust_find_channel_by_name(struct cds_lfht *ht, + char *name) { - struct ltt_ust_session *sess; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - if (session_list == NULL) { - ERR("Session list is NULL"); + rcu_read_lock(); + node = hashtable_lookup(ht, (void *) name, strlen(name), &iter); + if (node == NULL) { + rcu_read_unlock(); goto error; } + rcu_read_unlock(); - cds_list_for_each_entry(sess, &session_list->head, list) { - if (sess->domain.type == LTTNG_DOMAIN_UST_PID && - sess->domain.attr.pid == pid) { - DBG2("Trace UST session found by pid %d", pid); - return sess; - } - } - -error: - return NULL; -} + DBG2("Trace UST channel %s found by name", name); -/* - * Find the channel name for the given ust session. - */ -struct ltt_ust_channel *trace_ust_get_channel_by_name( - char *name, struct ltt_ust_session *session) -{ - struct ltt_ust_channel *chan; - - if (session == NULL) { - ERR("Undefine session"); - goto error; - } - - cds_list_for_each_entry(chan, &session->channels.head, list) { - if (strcmp(name, chan->name) == 0) { - DBG2("Found UST channel by name %s", name); - return chan; - } - } + return caa_container_of(node, struct ltt_ust_channel, node); error: + DBG2("Trace UST channel %s not found by name", name); return NULL; } /* - * Find the event name for the given channel. + * Find the event in the hashtable. */ -struct ltt_ust_event *trace_ust_get_event_by_name( - char *name, struct ltt_ust_channel *channel) +struct ltt_ust_event *trace_ust_find_event_by_name(struct cds_lfht *ht, + char *name) { - struct ltt_ust_event *ev; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - if (channel == NULL) { - ERR("Undefine channel"); + rcu_read_lock(); + node = hashtable_lookup(ht, (void *) name, strlen(name), &iter); + if (node == NULL) { + rcu_read_unlock(); goto error; } + rcu_read_unlock(); - cds_list_for_each_entry(ev, &channel->events.head, list) { - if (strcmp(name, ev->attr.name) == 0) { - DBG("Found UST event by name %s for channel %s", name, - channel->name); - return ev; - } - } + DBG2("Found UST event by name %s", name); + + return caa_container_of(node, struct ltt_ust_event, node); error: return NULL; @@ -106,7 +83,7 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, +struct ltt_ust_session *trace_ust_create_session(char *path, unsigned int uid, struct lttng_domain *domain) { int ret; @@ -120,18 +97,18 @@ struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid, } /* Init data structure */ - lus->handle = -1; - lus->enabled = 1; lus->consumer_fds_sent = 0; - lus->metadata = NULL; - lus->channels.count = 0; - CDS_INIT_LIST_HEAD(&lus->channels.head); + lus->uid = uid; + + /* Alloc UST domain hash tables */ + lus->domain_pid = hashtable_new(0); + lus->domain_exec = hashtable_new_str(0); - /* Copy lttng_domain */ - memcpy(&lus->domain, domain, sizeof(struct lttng_domain)); + /* Alloc UST global domain channels' HT */ + lus->domain_global.channels = hashtable_new_str(0); /* Set session path */ - ret = snprintf(lus->path, PATH_MAX, "%s/ust_%d", path, pid); + ret = snprintf(lus->pathname, PATH_MAX, "%s/ust", path); if (ret < 0) { PERROR("snprintf kernel traces path"); goto error; @@ -163,7 +140,12 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, } /* Copy UST channel attributes */ - memcpy(&luc->attr, &chan->attr, sizeof(struct lttng_ust_channel)); + luc->attr.overwrite = chan->attr.overwrite; + luc->attr.subbuf_size = chan->attr.subbuf_size; + luc->attr.num_subbuf = chan->attr.num_subbuf; + luc->attr.switch_timer_interval = chan->attr.switch_timer_interval; + luc->attr.read_timer_interval = chan->attr.read_timer_interval; + luc->attr.output = chan->attr.output; /* Translate to UST output enum */ switch (luc->attr.output) { @@ -172,24 +154,25 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, break; } - luc->handle = -1; - luc->enabled = 1; - luc->events.count = 0; - CDS_INIT_LIST_HEAD(&luc->events.head); - - memset(&luc->ctx, 0, sizeof(struct lttng_ust_context)); - /* Copy channel name */ strncpy(luc->name, chan->name, sizeof(&luc->name)); luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + /* Init node */ + hashtable_node_init(&luc->node, (void *) luc->name, strlen(luc->name)); + /* Alloc hash tables */ + luc->events = hashtable_new_str(0); + luc->ctx = hashtable_new_str(0); + /* Set trace output path */ - ret = snprintf(luc->trace_path, PATH_MAX, "%s", path); + ret = snprintf(luc->pathname, PATH_MAX, "%s", path); if (ret < 0) { perror("asprintf ust create channel"); goto error; } + DBG2("Trace UST channel %s created", luc->name); + return luc; error: @@ -233,10 +216,11 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - /* Setting up a ust event */ - lue->handle = -1; - lue->enabled = 1; - memset(&lue->ctx, 0, sizeof(struct lttng_ust_context)); + /* Init node */ + hashtable_node_init(&lue->node, (void *) lue->attr.name, + strlen(lue->attr.name)); + /* Alloc context hash tables */ + lue->ctx = hashtable_new_str(5); return lue; @@ -270,7 +254,7 @@ struct ltt_ust_metadata *trace_ust_create_metadata(char *path) lum->handle = -1; /* Set metadata trace path */ - ret = asprintf(&lum->trace_path, "%s/metadata", path); + ret = snprintf(lum->pathname, PATH_MAX, "%s/metadata", path); if (ret < 0) { perror("asprintf ust metadata"); goto error; @@ -282,35 +266,101 @@ error: return NULL; } +/* + * RCU safe free context structure. + */ +static void destroy_context_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_context *ctx = + caa_container_of(node, struct ltt_ust_context, node); + + free(ctx); +} + +/* + * Cleanup UST context hash table. + */ +static void destroy_context(struct cds_lfht *ht) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht, &iter); + if (!ret) { + call_rcu(&node->head, destroy_context_rcu); + } + hashtable_get_next(ht, &iter); + } +} + /* * Cleanup ust event structure. */ void trace_ust_destroy_event(struct ltt_ust_event *event) { - DBG("[trace] Destroy ust event %s", event->attr.name); - - /* Remove from event list */ - cds_list_del(&event->list); + DBG2("Trace destroy UST event %s", event->attr.name); + destroy_context(event->ctx); free(event); } +/* + * URCU intermediate call to complete destroy event. + */ +static void destroy_event_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_event *event = + caa_container_of(node, struct ltt_ust_event, node); + + trace_ust_destroy_event(event); +} + /* * Cleanup ust channel structure. */ void trace_ust_destroy_channel(struct ltt_ust_channel *channel) { - struct ltt_ust_event *event, *etmp; + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; - DBG("[trace] Destroy ust channel %d", channel->handle); + DBG2("Trace destroy UST channel %s", channel->name); - /* For each event in the channel list */ - cds_list_for_each_entry_safe(event, etmp, &channel->events.head, list) { - trace_ust_destroy_event(event); + rcu_read_lock(); + + hashtable_get_first(channel->events, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(channel->events, &iter); + if (!ret) { + call_rcu(&node->head, destroy_event_rcu); + } + hashtable_get_next(channel->events, &iter); } - /* Remove from channel list */ - cds_list_del(&channel->list); + free(channel->events); + destroy_context(channel->ctx); free(channel); + + rcu_read_unlock(); +} + +/* + * URCU intermediate call to complete destroy channel. + */ +static void destroy_channel_rcu(struct rcu_head *head) +{ + struct cds_lfht_node *node = + caa_container_of(head, struct cds_lfht_node, head); + struct ltt_ust_channel *channel = + caa_container_of(node, struct ltt_ust_channel, node); + + trace_ust_destroy_channel(channel); } /* @@ -318,39 +368,104 @@ void trace_ust_destroy_channel(struct ltt_ust_channel *channel) */ void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata) { - DBG("[trace] Destroy ust metadata %d", metadata->handle); - - /* Free attributes */ - free(metadata->trace_path); + DBG2("Trace UST destroy metadata %d", metadata->handle); free(metadata); } /* - * Cleanup ust session structure + * Iterate over a hash table containing channels and cleanup safely. */ -void trace_ust_destroy_session(struct ltt_ust_session *session) +static void destroy_channels(struct cds_lfht *channels) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + hashtable_get_first(channels, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(channels, &iter); + if (!ret) { + call_rcu(&node->head, destroy_channel_rcu); + } + hashtable_get_next(channels, &iter); + } +} + +/* + * Cleanup UST pid domain. + */ +static void destroy_domain_pid(struct cds_lfht *ht) +{ + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + struct ltt_ust_domain_pid *d; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht , &iter); + if (!ret) { + d = caa_container_of(node, struct ltt_ust_domain_pid, node); + destroy_channels(d->channels); + } + hashtable_get_next(ht, &iter); + } +} + +/* + * Cleanup UST exec name domain. + */ +static void destroy_domain_exec(struct cds_lfht *ht) { - struct ltt_ust_channel *channel, *ctmp; + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + struct ltt_ust_domain_exec *d; + + hashtable_get_first(ht, &iter); + while ((node = hashtable_iter_get_node(&iter)) != NULL) { + ret = hashtable_del(ht , &iter); + if (!ret) { + d = caa_container_of(node, struct ltt_ust_domain_exec, node); + destroy_channels(d->channels); + } + hashtable_get_next(ht, &iter); + } +} - DBG("[trace] Destroy ust session %d", session->handle); +/* + * Cleanup UST global domain. + */ +static void destroy_domain_global(struct ltt_ust_domain_global *dom) +{ + destroy_channels(dom->channels); +} +/* + * Cleanup ust session structure + */ +void trace_ust_destroy_session(struct ltt_ust_session *session) +{ /* Extra safety */ if (session == NULL) { return; } - if (session->metadata != NULL) { - trace_ust_destroy_metadata(session->metadata); - } + rcu_read_lock(); - cds_list_for_each_entry_safe(channel, ctmp, &session->channels.head, list) { - trace_ust_destroy_channel(channel); - } + DBG2("Trace UST destroy session %d", session->uid); - if (session->path) { - free(session->path); - } + //if (session->metadata != NULL) { + // trace_ust_destroy_metadata(session->metadata); + //} + + /* Cleaning up UST domain */ + destroy_domain_global(&session->domain_global); + destroy_domain_pid(session->domain_pid); + destroy_domain_exec(session->domain_exec); free(session); + + rcu_read_unlock(); }