+ 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;
+
+ /* 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) {
+ goto error;
+ }
+
+ return ua_event;
+
+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 *));