From 5b4a0ec04ce1ee5a4cf4c8a5896edab28750da56 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Tue, 15 Nov 2011 15:23:14 -0500 Subject: [PATCH] Cleanup and add comments to ust_app.c Mostly cleanup the code by moving static functions up and creating wrapper function around the ustctl_* API calls. Also, replace all hashtable iteration structure by cds each entry macros. Signed-off-by: David Goulet --- lttng-sessiond/main.c | 4 +- lttng-sessiond/ust-app.c | 890 ++++++++++++++++++++------------------- lttng-sessiond/ust-app.h | 4 +- 3 files changed, 468 insertions(+), 430 deletions(-) diff --git a/lttng-sessiond/main.c b/lttng-sessiond/main.c index ccdc50f1d..aae9b3dfe 100644 --- a/lttng-sessiond/main.c +++ b/lttng-sessiond/main.c @@ -2097,7 +2097,7 @@ static int cmd_enable_channel(struct ltt_session *session, } /* Add channel to all registered applications */ - ret = ust_app_add_channel_all(usess, uchan); + ret = ust_app_create_channel_all(usess, uchan); if (ret != 0) { goto error; } @@ -2360,7 +2360,7 @@ static int cmd_enable_event(struct ltt_session *session, int domain, } - ret = ust_app_add_event_all(usess, uchan, uevent); + ret = ust_app_create_event_all(usess, uchan, uevent); if (ret < 0) { ret = LTTCOMM_UST_ENABLE_FAIL; goto error; diff --git a/lttng-sessiond/ust-app.c b/lttng-sessiond/ust-app.c index 6e25c5b3e..43832aacb 100644 --- a/lttng-sessiond/ust-app.c +++ b/lttng-sessiond/ust-app.c @@ -237,237 +237,112 @@ error: } /* - * Return pointer to traceable apps list. - */ -struct cds_lfht *ust_app_get_ht(void) -{ - return ust_app_ht; -} - -/* - * Return ust app pointer or NULL if not found. + * Open metadata onto the UST tracer for a UST session. */ -struct ust_app *ust_app_find_by_pid(pid_t pid) +static int open_ust_metadata(struct ust_app *app, + struct ust_app_session *ua_sess) { - struct cds_lfht_node *node; - struct cds_lfht_iter iter; + int ret; + struct lttng_ust_channel_attr uattr; - rcu_read_lock(); - node = hashtable_lookup(ust_app_ht, - (void *)((unsigned long) pid), sizeof(void *), &iter); - if (node == NULL) { - DBG2("UST app no found with pid %d", pid); + uattr.overwrite = ua_sess->metadata->attr.overwrite; + uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size; + uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf; + uattr.switch_timer_interval = + ua_sess->metadata->attr.switch_timer_interval; + uattr.read_timer_interval = + ua_sess->metadata->attr.read_timer_interval; + uattr.output = ua_sess->metadata->attr.output; + + /* UST tracer metadata creation */ + ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr, + &ua_sess->metadata->obj); + if (ret < 0) { + ERR("UST app open metadata failed for app pid:%d", + app->key.pid); goto error; } - rcu_read_unlock(); - - DBG2("Found UST app by pid %d", pid); - - return caa_container_of(node, struct ust_app, node); error: - rcu_read_unlock(); - return NULL; -} - -/* - * Using pid and uid (of the app), allocate a new ust_app struct and - * add it to the global traceable app list. - * - * On success, return 0, else return malloc ENOMEM. - */ -int ust_app_register(struct ust_register_msg *msg, int sock) -{ - struct ust_app *lta; - - lta = zmalloc(sizeof(struct ust_app)); - if (lta == NULL) { - PERROR("malloc"); - return -ENOMEM; - } - - lta->ppid = msg->ppid; - lta->uid = msg->uid; - lta->gid = msg->gid; - lta->v_major = msg->major; - lta->v_minor = msg->minor; - strncpy(lta->name, msg->name, sizeof(lta->name)); - lta->name[16] = '\0'; - lta->sessions = hashtable_new(0); - - /* Set key map */ - lta->key.pid = msg->pid; - hashtable_node_init(<a->node, (void *)((unsigned long)lta->key.pid), - sizeof(void *)); - lta->key.sock = sock; - hashtable_node_init(<a->key.node, (void *)((unsigned long)lta->key.sock), - sizeof(void *)); - - rcu_read_lock(); - hashtable_add_unique(ust_app_sock_key_map, <a->key.node); - hashtable_add_unique(ust_app_ht, <a->node); - rcu_read_unlock(); - - DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s" - " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid, - lta->key.sock, lta->name, lta->v_major, lta->v_minor); - - return 0; + return ret; } /* - * Unregister app by removing it from the global traceable app list and freeing - * the data struct. - * - * The socket is already closed at this point so no close to sock. + * Create stream onto the UST tracer for a UST session. */ -void ust_app_unregister(int sock) +static int create_ust_stream(struct ust_app *app, + struct ust_app_session *ua_sess) { - struct ust_app *lta; - struct cds_lfht_node *node; - struct cds_lfht_iter iter; - - rcu_read_lock(); - lta = find_app_by_sock(sock); - if (lta == NULL) { - ERR("Unregister app sock %d not found!", sock); - goto error; - } - - DBG("PID %d unregistering with sock %d", lta->key.pid, sock); + int ret; - /* Get the node reference for a call_rcu */ - node = hashtable_lookup(ust_app_ht, - (void *)((unsigned long) lta->key.pid), sizeof(void *), &iter); - if (node == NULL) { - ERR("Unable to find app sock %d by pid %d", sock, lta->key.pid); + ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj, + &ua_sess->metadata->stream_obj); + if (ret < 0) { + ERR("UST create metadata stream failed"); goto error; } - /* We got called because the socket was closed on the remote end. */ - close(sock); - /* Using a flag because we still need "sock" as a key. */ - lta->sock_closed = 1; - hashtable_del(ust_app_ht, &iter); - call_rcu(&node->head, delete_ust_app_rcu); error: - rcu_read_unlock(); - return; -} - -/* - * Return traceable_app_count - */ -unsigned long ust_app_list_count(void) -{ - unsigned long count; - - rcu_read_lock(); - count = hashtable_get_count(ust_app_ht); - rcu_read_unlock(); - - return count; + return ret; } /* - * Fill events array with all events name of all registered apps. + * Create the specified channel onto the UST tracer for a UST session. */ -int ust_app_list_events(struct lttng_event **events) +static int create_ust_channel(struct ust_app *app, + struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan) { - int ret, handle; - size_t nbmem, count = 0; - struct cds_lfht_iter iter; - struct ust_app *app; - struct lttng_event *tmp; + int ret; - nbmem = UST_APP_EVENT_LIST_SIZE; - tmp = zmalloc(nbmem * sizeof(struct lttng_event)); - if (tmp == NULL) { - PERROR("zmalloc ust app events"); - ret = -ENOMEM; + /* TODO: remove cast and use lttng-ust-abi.h */ + ret = ustctl_create_channel(app->key.sock, ua_sess->handle, + (struct lttng_ust_channel_attr *)&ua_chan->attr, &ua_chan->obj); + if (ret < 0) { + DBG("Error creating channel %s for app (pid: %d, sock: %d) " + "and session handle %d with ret %d", + ua_chan->name, app->key.pid, app->key.sock, + ua_sess->handle, ret); goto error; } - rcu_read_lock(); - - cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { - handle = ustctl_tracepoint_list(app->key.sock); - if (handle < 0) { - ERR("UST app list events getting handle failed for app pid %d", - app->key.pid); - continue; - } - - while ((ret = ustctl_tracepoint_list_get(app->key.sock, handle, - tmp[count].name)) != -ENOENT) { - if (count > nbmem) { - DBG2("Reallocating event list from %zu to %zu bytes", nbmem, - nbmem + UST_APP_EVENT_LIST_SIZE); - nbmem += UST_APP_EVENT_LIST_SIZE; - tmp = realloc(tmp, nbmem); - if (tmp == NULL) { - PERROR("realloc ust app events"); - ret = -ENOMEM; - goto rcu_error; - } - } - - tmp[count].type = LTTNG_UST_TRACEPOINT; - tmp[count].pid = app->key.pid; - tmp[count].enabled = -1; - count++; - } - } - - ret = count; - *events = tmp; + ua_chan->handle = ua_chan->obj->handle; + ua_chan->attr.shm_fd = ua_chan->obj->shm_fd; + ua_chan->attr.wait_fd = ua_chan->obj->wait_fd; + ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size; - DBG2("UST app list events done (%zu events)", count); + DBG2("UST app channel %s created successfully for pid:%d and sock:%d", + ua_chan->name, app->key.pid, app->key.sock); -rcu_error: - rcu_read_unlock(); error: return ret; } /* - * Free and clean all traceable apps of the global list. + * Create the specified event onto the UST tracer for a UST session. */ -void ust_app_clean_list(void) +static int create_ust_event(struct ust_app *app, + struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, + struct ust_app_event *ua_event) { - int ret; - struct cds_lfht_node *node; - struct cds_lfht_iter iter; - struct ust_app *app; - - DBG2("UST app cleaning registered apps hash table"); - - rcu_read_lock(); - - cds_lfht_for_each(ust_app_ht, &iter, node) { - app = caa_container_of(node, struct ust_app, node); - close(app->key.sock); - app->sock_closed = 1; + int ret = 0; - ret = hashtable_del(ust_app_ht, &iter); - if (!ret) { - call_rcu(&node->head, delete_ust_app_rcu); - } + /* Create UST event on tracer */ + ret = ustctl_create_event(app->key.sock, &ua_event->attr, ua_chan->obj, + &ua_event->obj); + if (ret < 0) { + ERR("Error ustctl create event %s for app pid: %d with ret %d", + ua_event->attr.name, app->key.pid, ret); + goto error; } - hashtable_destroy(ust_app_ht); - hashtable_destroy(ust_app_sock_key_map); + ua_event->handle = ua_event->obj->handle; + ua_event->enabled = 1; - rcu_read_unlock(); -} + DBG2("UST app event %s created successfully for pid:%d", + ua_event->attr.name, app->key.pid); -/* - * Init UST app hash table. - */ -void ust_app_ht_alloc(void) -{ - ust_app_ht = hashtable_new(0); - ust_app_sock_key_map = hashtable_new(0); +error: + return ret; } /* @@ -567,20 +442,29 @@ error: return NULL; } +/* + * Copy data between an UST app event and a LTT event. + */ static void shadow_copy_event(struct ust_app_event *ua_event, struct ltt_ust_event *uevent) { strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name)); ua_event->name[sizeof(ua_event->name) - 1] = '\0'; + /* Copy event attributes */ + memcpy(&ua_event->attr, &uevent->attr, sizeof(ua_event->attr)); + /* TODO: support copy context */ } +/* + * Copy data between an UST app channel and a LTT channel. + */ static void shadow_copy_channel(struct ust_app_channel *ua_chan, struct ltt_ust_channel *uchan) { struct cds_lfht_iter iter; - struct cds_lfht_node *node, *ua_event_node; + struct cds_lfht_node *ua_event_node; struct ltt_ust_event *uevent; struct ust_app_event *ua_event; @@ -588,14 +472,13 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name)); ua_chan->name[sizeof(ua_chan->name) - 1] = '\0'; + /* Copy event attributes */ + memcpy(&ua_chan->attr, &uchan->attr, sizeof(ua_chan->attr)); /* TODO: support copy context */ /* Copy all events from ltt ust channel to ust app channel */ - hashtable_get_first(uchan->events, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - uevent = caa_container_of(node, struct ltt_ust_event, node); - + cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) { ua_event_node = hashtable_lookup(ua_chan->events, (void *) uevent->attr.name, strlen(uevent->attr.name), &iter); if (ua_event_node == NULL) { @@ -603,24 +486,23 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, uevent->attr.name); ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr); if (ua_event == NULL) { - goto next; + continue; } shadow_copy_event(ua_event, uevent); hashtable_add_unique(ua_chan->events, &ua_event->node); } - -next: - /* Get next UST events */ - hashtable_get_next(uchan->events, &iter); } DBG3("Shadow copy channel done"); } +/* + * Copy data between a UST app session and a regular LTT session. + */ static void shadow_copy_session(struct ust_app_session *ua_sess, struct ltt_ust_session *usess) { - struct cds_lfht_node *node, *ua_chan_node; + struct cds_lfht_node *ua_chan_node; struct cds_lfht_iter iter; struct ltt_ust_channel *uchan; struct ust_app_channel *ua_chan; @@ -632,28 +514,24 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, /* TODO: support all UST domain */ /* Iterate over all channels in global domain. */ - hashtable_get_first(usess->domain_global.channels, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - uchan = caa_container_of(node, struct ltt_ust_channel, node); - + cds_lfht_for_each_entry(usess->domain_global.channels, &iter, + uchan, node) { ua_chan_node = hashtable_lookup(ua_sess->channels, (void *)uchan->name, strlen(uchan->name), &iter); - if (ua_chan_node == NULL) { - DBG2("Channel %s not found on shadow session copy, creating it", - uchan->name); - ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr); - if (ua_chan == NULL) { - /* malloc failed... continuing */ - goto next; - } + if (ua_chan_node != NULL) { + continue; + } - shadow_copy_channel(ua_chan, uchan); - hashtable_add_unique(ua_sess->channels, &ua_chan->node); + DBG2("Channel %s not found on shadow session copy, creating it", + uchan->name); + ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr); + if (ua_chan == NULL) { + /* malloc failed... continuing */ + continue; } -next: - /* Next item in hash table */ - hashtable_get_next(usess->domain_global.channels, &iter); + shadow_copy_channel(ua_chan, uchan); + hashtable_add_unique(ua_sess->channels, &ua_chan->node); } } @@ -731,223 +609,393 @@ error: } /* - * Create the specified channel onto the UST tracer for a UST session. + * Create UST app channel and create it on the tracer. */ -static int create_ust_channel(struct ust_app *app, - struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan) +static struct ust_app_channel *create_ust_app_channel( + struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan, + struct ust_app *app) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct cds_lfht_node *ua_chan_node; + struct ust_app_channel *ua_chan; + + /* Lookup channel in the ust app session */ + ua_chan_node = hashtable_lookup(ua_sess->channels, + (void *)uchan->name, strlen(uchan->name), &iter); + if (ua_chan_node == NULL) { + DBG2("Unable to find channel %s in ust session uid %u", + uchan->name, ua_sess->uid); + ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr); + if (ua_chan == NULL) { + goto error; + } + shadow_copy_channel(ua_chan, uchan); + + hashtable_add_unique(ua_sess->channels, &ua_chan->node); + } else { + ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); + } + + ret = create_ust_channel(app, ua_sess, ua_chan); + if (ret < 0) { + goto error; + } + + return ua_chan; + +error: + return NULL; +} + +/* + * Create UST app event and create it on the tracer side. + */ +static struct ust_app_event *create_ust_app_event( + struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, + struct ltt_ust_event *uevent, struct ust_app *app) { int ret; + struct cds_lfht_iter iter; + struct cds_lfht_node *ua_event_node; + struct ust_app_event *ua_event; - /* TODO: remove cast and use lttng-ust-abi.h */ - ret = ustctl_create_channel(app->key.sock, ua_sess->handle, - (struct lttng_ust_channel_attr *)&ua_chan->attr, &ua_chan->obj); + /* Get event node */ + ua_event_node = hashtable_lookup(ua_chan->events, + (void *)uevent->attr.name, strlen(uevent->attr.name), &iter); + if (ua_event_node == NULL) { + DBG2("UST app event %s not found, creating it", uevent->attr.name); + /* Does not exist so create one */ + ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr); + if (ua_event == NULL) { + /* Only malloc can failed so something is really wrong */ + goto error; + } + shadow_copy_event(ua_event, uevent); + + hashtable_add_unique(ua_chan->events, &ua_event->node); + } else { + ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); + } + + ret = create_ust_event(app, ua_sess, ua_chan, ua_event); if (ret < 0) { - DBG("Error creating channel %s for app (pid: %d, sock: %d) " - "and session handle %d with ret %d", - ua_chan->name, app->key.pid, app->key.sock, - ua_sess->handle, ret); goto error; } - ua_chan->handle = ua_chan->obj->handle; - ua_chan->attr.shm_fd = ua_chan->obj->shm_fd; - ua_chan->attr.wait_fd = ua_chan->obj->wait_fd; - ua_chan->attr.memory_map_size = ua_chan->obj->memory_map_size; + return ua_event; - DBG2("UST app channel %s created successfully for pid:%d and sock:%d", - ua_chan->name, app->key.pid, app->key.sock); +error: + return NULL; +} + +/* + * Create UST metadata and open it on the tracer side. + */ +static int create_ust_app_metadata(struct ust_app_session *ua_sess, + char *pathname, struct ust_app *app) +{ + int ret = 0; + + if (ua_sess->metadata == NULL) { + /* Allocate UST metadata */ + ua_sess->metadata = trace_ust_create_metadata(pathname); + if (ua_sess->metadata == NULL) { + ERR("UST app session %d creating metadata failed", + ua_sess->handle); + goto error; + } + + ret = open_ust_metadata(app, ua_sess); + if (ret < 0) { + goto error; + } + + DBG2("UST metadata opened for app pid %d", app->key.pid); + } + + /* Open UST metadata stream */ + if (ua_sess->metadata->stream_obj == NULL) { + ret = create_ust_stream(app, ua_sess); + if (ret < 0) { + goto error; + } + + ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d", + pathname, app->name, app->key.pid); + if (ret < 0) { + PERROR("asprintf UST create stream"); + goto error; + } + + ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG); + if (ret < 0) { + PERROR("mkdir UST metadata"); + goto error; + } + + ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata", + pathname, app->name, app->key.pid); + if (ret < 0) { + PERROR("asprintf UST create stream"); + goto error; + } + + DBG2("UST metadata stream object created for app pid %d", + app->key.pid); + } else { + ERR("Attempting to create stream without metadata opened"); + goto error; + } + + return 0; + +error: + return -1; +} + +/* + * Return pointer to traceable apps list. + */ +struct cds_lfht *ust_app_get_ht(void) +{ + return ust_app_ht; +} + +/* + * Return ust app pointer or NULL if not found. + */ +struct ust_app *ust_app_find_by_pid(pid_t pid) +{ + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + rcu_read_lock(); + node = hashtable_lookup(ust_app_ht, + (void *)((unsigned long) pid), sizeof(void *), &iter); + if (node == NULL) { + DBG2("UST app no found with pid %d", pid); + goto error; + } + rcu_read_unlock(); + + DBG2("Found UST app by pid %d", pid); + + return caa_container_of(node, struct ust_app, node); + +error: + rcu_read_unlock(); + return NULL; +} + +/* + * Using pid and uid (of the app), allocate a new ust_app struct and + * add it to the global traceable app list. + * + * On success, return 0, else return malloc ENOMEM. + */ +int ust_app_register(struct ust_register_msg *msg, int sock) +{ + struct ust_app *lta; + + lta = zmalloc(sizeof(struct ust_app)); + if (lta == NULL) { + PERROR("malloc"); + return -ENOMEM; + } + + lta->ppid = msg->ppid; + lta->uid = msg->uid; + lta->gid = msg->gid; + lta->v_major = msg->major; + lta->v_minor = msg->minor; + strncpy(lta->name, msg->name, sizeof(lta->name)); + lta->name[16] = '\0'; + lta->sessions = hashtable_new(0); + + /* Set key map */ + lta->key.pid = msg->pid; + hashtable_node_init(<a->node, (void *)((unsigned long)lta->key.pid), + sizeof(void *)); + lta->key.sock = sock; + hashtable_node_init(<a->key.node, (void *)((unsigned long)lta->key.sock), + sizeof(void *)); + + rcu_read_lock(); + hashtable_add_unique(ust_app_sock_key_map, <a->key.node); + hashtable_add_unique(ust_app_ht, <a->node); + rcu_read_unlock(); + + DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s" + " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid, + lta->key.sock, lta->name, lta->v_major, lta->v_minor); + + return 0; +} + +/* + * Unregister app by removing it from the global traceable app list and freeing + * the data struct. + * + * The socket is already closed at this point so no close to sock. + */ +void ust_app_unregister(int sock) +{ + struct ust_app *lta; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + + rcu_read_lock(); + lta = find_app_by_sock(sock); + if (lta == NULL) { + ERR("Unregister app sock %d not found!", sock); + goto error; + } + + DBG("PID %d unregistering with sock %d", lta->key.pid, sock); + + /* Get the node reference for a call_rcu */ + node = hashtable_lookup(ust_app_ht, + (void *)((unsigned long) lta->key.pid), sizeof(void *), &iter); + if (node == NULL) { + ERR("Unable to find app sock %d by pid %d", sock, lta->key.pid); + goto error; + } + /* We got called because the socket was closed on the remote end. */ + close(sock); + /* Using a flag because we still need "sock" as a key. */ + lta->sock_closed = 1; + hashtable_del(ust_app_ht, &iter); + call_rcu(&node->head, delete_ust_app_rcu); error: - return ret; + rcu_read_unlock(); + return; } /* - * Create the specified event onto the UST tracer for a UST session. + * Return traceable_app_count */ -static int create_ust_event(struct ust_app *app, - struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, - struct ust_app_event *ua_event) +unsigned long ust_app_list_count(void) { - int ret = 0; - - /* Create UST event on tracer */ - ret = ustctl_create_event(app->key.sock, &ua_event->attr, ua_chan->obj, - &ua_event->obj); - if (ret < 0) { - ERR("Error ustctl create event %s for app pid: %d with ret %d", - ua_event->attr.name, app->key.pid, ret); - goto error; - } - - ua_event->handle = ua_event->obj->handle; - ua_event->enabled = 1; + unsigned long count; - DBG2("UST app event %s created successfully for pid:%d", - ua_event->attr.name, app->key.pid); + rcu_read_lock(); + count = hashtable_get_count(ust_app_ht); + rcu_read_unlock(); -error: - return ret; + return count; } -static struct ust_app_channel *create_ust_app_channel( - struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan, - struct ust_app *app) +/* + * Fill events array with all events name of all registered apps. + */ +int ust_app_list_events(struct lttng_event **events) { - int ret = 0; + int ret, handle; + size_t nbmem, count = 0; struct cds_lfht_iter iter; - struct cds_lfht_node *ua_chan_node; - struct ust_app_channel *ua_chan; - - /* Lookup channel in the ust app session */ - ua_chan_node = hashtable_lookup(ua_sess->channels, - (void *)uchan->name, strlen(uchan->name), &iter); - if (ua_chan_node == NULL) { - DBG2("Unable to find channel %s in ust session uid %u", - uchan->name, ua_sess->uid); - ua_chan = alloc_ust_app_channel(uchan->name, &uchan->attr); - if (ua_chan == NULL) { - goto error; - } - shadow_copy_channel(ua_chan, uchan); - - hashtable_add_unique(ua_sess->channels, &ua_chan->node); - } else { - ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - } + struct ust_app *app; + struct lttng_event *tmp; - ret = create_ust_channel(app, ua_sess, ua_chan); - if (ret < 0) { + nbmem = UST_APP_EVENT_LIST_SIZE; + tmp = zmalloc(nbmem * sizeof(struct lttng_event)); + if (tmp == NULL) { + PERROR("zmalloc ust app events"); + ret = -ENOMEM; goto error; } - return ua_chan; + rcu_read_lock(); -error: - return NULL; -} + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { + handle = ustctl_tracepoint_list(app->key.sock); + if (handle < 0) { + ERR("UST app list events getting handle failed for app pid %d", + app->key.pid); + continue; + } -static struct ust_app_event *create_ust_app_event( - struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, - struct ltt_ust_event *uevent, struct ust_app *app) -{ - int ret; - struct cds_lfht_iter iter; - struct cds_lfht_node *ua_event_node; - struct ust_app_event *ua_event; + while ((ret = ustctl_tracepoint_list_get(app->key.sock, handle, + tmp[count].name)) != -ENOENT) { + if (count > nbmem) { + DBG2("Reallocating event list from %zu to %zu bytes", nbmem, + nbmem + UST_APP_EVENT_LIST_SIZE); + nbmem += UST_APP_EVENT_LIST_SIZE; + tmp = realloc(tmp, nbmem); + if (tmp == NULL) { + PERROR("realloc ust app events"); + ret = -ENOMEM; + goto rcu_error; + } + } - /* Get event node */ - ua_event_node = hashtable_lookup(ua_chan->events, - (void *)uevent->attr.name, strlen(uevent->attr.name), &iter); - if (ua_event_node == NULL) { - DBG2("UST app event %s not found, creating it", uevent->attr.name); - /* Does not exist so create one */ - ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr); - if (ua_event == NULL) { - /* Only malloc can failed so something is really wrong */ - goto error; + tmp[count].type = LTTNG_UST_TRACEPOINT; + tmp[count].pid = app->key.pid; + tmp[count].enabled = -1; + count++; } - shadow_copy_event(ua_event, uevent); - - hashtable_add_unique(ua_chan->events, &ua_event->node); - } else { - ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); } - ret = create_ust_event(app, ua_sess, ua_chan, ua_event); - if (ret < 0) { - goto error; - } + ret = count; + *events = tmp; - return ua_event; + DBG2("UST app list events done (%zu events)", count); +rcu_error: + rcu_read_unlock(); error: - return NULL; + return ret; } -static int create_ust_app_metadata(struct ust_app_session *ua_sess, - char *pathname, struct ust_app *app) +/* + * Free and clean all traceable apps of the global list. + */ +void ust_app_clean_list(void) { - int ret = 0; - struct lttng_ust_channel_attr uattr; - - if (ua_sess->metadata == NULL) { - /* Allocate UST metadata */ - ua_sess->metadata = trace_ust_create_metadata(pathname); - if (ua_sess->metadata == NULL) { - ERR("UST app session %d creating metadata failed", - ua_sess->handle); - goto error; - } - - uattr.overwrite = ua_sess->metadata->attr.overwrite; - uattr.subbuf_size = ua_sess->metadata->attr.subbuf_size; - uattr.num_subbuf = ua_sess->metadata->attr.num_subbuf; - uattr.switch_timer_interval = - ua_sess->metadata->attr.switch_timer_interval; - uattr.read_timer_interval = - ua_sess->metadata->attr.read_timer_interval; - uattr.output = ua_sess->metadata->attr.output; - - /* UST tracer metadata creation */ - ret = ustctl_open_metadata(app->key.sock, ua_sess->handle, &uattr, - &ua_sess->metadata->obj); - if (ret < 0) { - ERR("UST app open metadata failed for app pid:%d", - app->key.pid); - goto error; - } - - DBG2("UST metadata opened for app pid %d", app->key.pid); - } + int ret; + struct cds_lfht_node *node; + struct cds_lfht_iter iter; + struct ust_app *app; - /* Open UST metadata stream */ - if (ua_sess->metadata->stream_obj == NULL) { - ret = ustctl_create_stream(app->key.sock, ua_sess->metadata->obj, - &ua_sess->metadata->stream_obj); - if (ret < 0) { - ERR("UST create metadata stream failed"); - goto error; - } + DBG2("UST app cleaning registered apps hash table"); - ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d", - pathname, app->name, app->key.pid); - if (ret < 0) { - PERROR("asprintf UST create stream"); - goto error; - } + rcu_read_lock(); - ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG); - if (ret < 0) { - PERROR("mkdir UST metadata"); - goto error; - } + cds_lfht_for_each(ust_app_ht, &iter, node) { + app = caa_container_of(node, struct ust_app, node); + close(app->key.sock); + app->sock_closed = 1; - ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata", - pathname, app->name, app->key.pid); - if (ret < 0) { - PERROR("asprintf UST create stream"); - goto error; + ret = hashtable_del(ust_app_ht, &iter); + if (!ret) { + call_rcu(&node->head, delete_ust_app_rcu); } - - DBG2("UST metadata stream object created for app pid %d", - app->key.pid); } - return 0; + hashtable_destroy(ust_app_ht); + hashtable_destroy(ust_app_sock_key_map); -error: - return -1; + rcu_read_unlock(); +} + +/* + * Init UST app hash table. + */ +void ust_app_ht_alloc(void) +{ + ust_app_ht = hashtable_new(0); + ust_app_sock_key_map = hashtable_new(0); } /* - * Add channel to all ust app session. + * For a specific UST session, create the channel for all registered apps. */ -int ust_app_add_channel_all(struct ltt_ust_session *usess, +int ust_app_create_channel_all(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan) { int ret = 0; struct cds_lfht_iter iter; - struct cds_lfht_node *node; struct ust_app *app; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; @@ -963,39 +1011,37 @@ int ust_app_add_channel_all(struct ltt_ust_session *usess, rcu_read_lock(); - /* For every UST applications registered */ - hashtable_get_first(ust_app_ht, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - app = caa_container_of(node, struct ust_app, node); - + /* For every registered applications */ + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { /* Create session on the tracer side and add it to app session HT */ ua_sess = create_ust_app_session(usess, app); if (ua_sess == NULL) { - goto next; + continue; } /* Create channel onto application */ ua_chan = create_ust_app_channel(ua_sess, uchan, app); if (ua_chan == NULL) { - goto next; + continue; } - -next: - /* Next applications */ - hashtable_get_next(ust_app_ht, &iter); } + rcu_read_unlock(); error: return ret; } -int ust_app_add_event_all(struct ltt_ust_session *usess, +/* + * For a specific UST session and UST channel, create the event for all + * registered apps. + */ +int ust_app_create_event_all(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent) { int ret = 0; struct cds_lfht_iter iter; - struct cds_lfht_node *node, *ua_chan_node; + struct cds_lfht_node *ua_chan_node; struct ust_app *app; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; @@ -1007,14 +1053,11 @@ int ust_app_add_event_all(struct ltt_ust_session *usess, rcu_read_lock(); /* For all registered applications */ - hashtable_get_first(ust_app_ht, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - app = caa_container_of(node, struct ust_app, node); - + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { /* Create session on the tracer side and add it to app session HT */ ua_sess = create_ust_app_session(usess, app); if (ua_sess == NULL) { - goto next; + continue; } /* Lookup channel in the ust app session */ @@ -1023,31 +1066,31 @@ int ust_app_add_event_all(struct ltt_ust_session *usess, if (ua_chan_node == NULL) { ERR("Channel %s not found in session uid %d. Skipping", uchan->name, usess->uid); - goto next; + continue; } ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); ua_event = create_ust_app_event(ua_sess, ua_chan, uevent, app); if (ua_event == NULL) { - goto next; + continue; } - -next: - /* Next applications */ - hashtable_get_next(ust_app_ht, &iter); } + rcu_read_unlock(); return ret; } +/* + * Start tracing for a specific UST session and app. + */ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) { int ret = 0; struct cds_lfht_iter iter; - struct cds_lfht_node *node; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; + struct ltt_ust_stream *ustream; DBG("Starting tracing for ust app pid %d", app->key.pid); @@ -1065,14 +1108,10 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) } /* For each channel */ - hashtable_get_first(ua_sess->channels, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - ua_chan = caa_container_of(node, struct ust_app_channel, node); - + cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) { /* Create all streams */ while (1) { - struct ltt_ust_stream *ustream; - + /* Create UST stream */ ustream = zmalloc(sizeof(*ustream)); if (ustream == NULL) { PERROR("zmalloc ust stream"); @@ -1099,9 +1138,6 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) DBG2("UST stream %d ready at %s", ua_chan->streams.count, ustream->pathname); } - - /* Next applications */ - hashtable_get_next(ua_sess->channels, &iter); } /* Setup UST consumer socket and send fds to it */ @@ -1116,6 +1152,7 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) ERR("Error starting tracing for app pid: %d", app->key.pid); goto error_rcu_unlock; } + rcu_read_unlock(); /* Quiescent wait after starting trace */ @@ -1128,34 +1165,35 @@ error_rcu_unlock: return -1; } +/* + * Start tracing for the UST session. + */ int ust_app_start_trace_all(struct ltt_ust_session *usess) { int ret = 0; struct cds_lfht_iter iter; - struct cds_lfht_node *node; struct ust_app *app; DBG("Starting all UST traces"); rcu_read_lock(); - hashtable_get_first(ust_app_ht, &iter); - while ((node = hashtable_iter_get_node(&iter)) != NULL) { - app = caa_container_of(node, struct ust_app, node); + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { ret = ust_app_start_trace(usess, app); if (ret < 0) { - goto next; + /* Continue to next apps even on error */ + continue; } - -next: - /* Next applications */ - hashtable_get_next(ust_app_ht, &iter); } + rcu_read_unlock(); return 0; } +/* + * Add channels/events from UST global domain to registered apps at sock. + */ void ust_app_global_update(struct ltt_ust_session *usess, int sock) { int ret = 0; @@ -1166,7 +1204,7 @@ void ust_app_global_update(struct ltt_ust_session *usess, int sock) struct ust_app_event *ua_event; if (usess == NULL) { - DBG2("No UST session on global update. Returning"); + ERR("No UST session on global update. Returning"); goto error; } diff --git a/lttng-sessiond/ust-app.h b/lttng-sessiond/ust-app.h index 3fa4d423c..f369a8a2f 100644 --- a/lttng-sessiond/ust-app.h +++ b/lttng-sessiond/ust-app.h @@ -105,9 +105,9 @@ struct ust_app { int ust_app_register(struct ust_register_msg *msg, int sock); void ust_app_unregister(int sock); -int ust_app_add_channel_all(struct ltt_ust_session *usess, +int ust_app_create_channel_all(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan); -int ust_app_add_event_all(struct ltt_ust_session *usess, +int ust_app_create_event_all(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent); unsigned long ust_app_list_count(void); int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app); -- 2.34.1