+end:
+ return ret;
+
+error:
+ /* Valid. Calling here is already in a read side lock */
+ delete_ust_app_event(-1, ua_event);
+ return ret;
+}
+
+/*
+ * Create UST metadata and open it on the tracer side.
+ *
+ * Called with UST app session lock held and RCU read side lock.
+ */
+static int create_ust_app_metadata(struct ust_app_session *ua_sess,
+ struct ust_app *app, struct consumer_output *consumer,
+ struct ustctl_consumer_channel_attr *attr)
+{
+ int ret = 0;
+ struct ust_app_channel *metadata;
+ struct consumer_socket *socket;
+ struct ust_registry_session *registry;
+
+ assert(ua_sess);
+ assert(app);
+ assert(consumer);
+
+ registry = get_session_registry(ua_sess);
+ assert(registry);
+
+ /* Metadata already exists for this registry or it was closed previously */
+ if (registry->metadata_key || registry->metadata_closed) {
+ ret = 0;
+ goto error;
+ }
+
+ /* Allocate UST metadata */
+ metadata = alloc_ust_app_channel(DEFAULT_METADATA_NAME, ua_sess, NULL);
+ if (!metadata) {
+ /* malloc() failed */
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (!attr) {
+ /* Set default attributes for metadata. */
+ metadata->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ metadata->attr.subbuf_size = default_get_metadata_subbuf_size();
+ metadata->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM;
+ metadata->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER;
+ metadata->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER;
+ metadata->attr.output = LTTNG_UST_MMAP;
+ metadata->attr.type = LTTNG_UST_CHAN_METADATA;
+ } else {
+ memcpy(&metadata->attr, attr, sizeof(metadata->attr));
+ metadata->attr.output = LTTNG_UST_MMAP;
+ metadata->attr.type = LTTNG_UST_CHAN_METADATA;
+ }
+
+ /* Need one fd for the channel. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 1);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon create metadata");
+ goto error;
+ }
+
+ /* Get the right consumer socket for the application. */
+ socket = consumer_find_socket_by_bitness(app->bits_per_long, consumer);
+ if (!socket) {
+ ret = -EINVAL;
+ goto error_consumer;
+ }
+
+ /*
+ * Keep metadata key so we can identify it on the consumer side. Assign it
+ * to the registry *before* we ask the consumer so we avoid the race of the
+ * consumer requesting the metadata and the ask_channel call on our side
+ * did not returned yet.
+ */
+ registry->metadata_key = metadata->key;
+
+ /*
+ * Ask the metadata channel creation to the consumer. The metadata object
+ * will be created by the consumer and kept their. However, the stream is
+ * never added or monitored until we do a first push metadata to the
+ * consumer.
+ */
+ ret = ust_consumer_ask_channel(ua_sess, metadata, consumer, socket,
+ registry);
+ if (ret < 0) {
+ /* Nullify the metadata key so we don't try to close it later on. */
+ registry->metadata_key = 0;
+ goto error_consumer;
+ }
+
+ /*
+ * The setup command will make the metadata stream be sent to the relayd,
+ * if applicable, and the thread managing the metadatas. This is important
+ * because after this point, if an error occurs, the only way the stream
+ * can be deleted is to be monitored in the consumer.
+ */
+ ret = consumer_setup_metadata(socket, metadata->key);
+ if (ret < 0) {
+ /* Nullify the metadata key so we don't try to close it later on. */
+ registry->metadata_key = 0;
+ goto error_consumer;
+ }
+
+ DBG2("UST metadata with key %" PRIu64 " created for app pid %d",
+ metadata->key, app->pid);
+
+error_consumer:
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+ delete_ust_app_channel(-1, metadata, app);
+error:
+ return ret;
+}
+
+/*
+ * Return pointer to traceable apps list.
+ */
+struct lttng_ht *ust_app_get_ht(void)
+{
+ return ust_app_ht;
+}
+
+/*
+ * Return ust app pointer or NULL if not found. RCU read side lock MUST be
+ * acquired before calling this function.
+ */
+struct ust_app *ust_app_find_by_pid(pid_t pid)
+{
+ struct ust_app *app = NULL;
+ struct lttng_ht_node_ulong *node;
+ struct lttng_ht_iter iter;
+
+ lttng_ht_lookup(ust_app_ht, (void *)((unsigned long) pid), &iter);
+ node = lttng_ht_iter_get_node_ulong(&iter);
+ if (node == NULL) {
+ DBG2("UST app no found with pid %d", pid);
+ goto error;
+ }
+
+ DBG2("Found UST app by pid %d", pid);
+
+ app = caa_container_of(node, struct ust_app, pid_n);
+
+error:
+ return app;
+}
+
+/*
+ * Allocate and init an UST app object using the registration information and
+ * the command socket. This is called when the command socket connects to the
+ * session daemon.
+ *
+ * The object is returned on success or else NULL.
+ */
+struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
+{
+ struct ust_app *lta = NULL;
+
+ assert(msg);
+ assert(sock >= 0);
+
+ DBG3("UST app creating application for socket %d", sock);
+
+ if ((msg->bits_per_long == 64 &&
+ (uatomic_read(&ust_consumerd64_fd) == -EINVAL))
+ || (msg->bits_per_long == 32 &&
+ (uatomic_read(&ust_consumerd32_fd) == -EINVAL))) {
+ ERR("Registration failed: application \"%s\" (pid: %d) has "
+ "%d-bit long, but no consumerd for this size is available.\n",
+ msg->name, msg->pid, msg->bits_per_long);
+ goto error;
+ }
+
+ lta = zmalloc(sizeof(struct ust_app));
+ if (lta == NULL) {
+ PERROR("malloc");
+ goto error;
+ }
+
+ lta->ppid = msg->ppid;
+ lta->uid = msg->uid;
+ lta->gid = msg->gid;
+
+ lta->bits_per_long = msg->bits_per_long;
+ lta->uint8_t_alignment = msg->uint8_t_alignment;
+ lta->uint16_t_alignment = msg->uint16_t_alignment;
+ lta->uint32_t_alignment = msg->uint32_t_alignment;
+ lta->uint64_t_alignment = msg->uint64_t_alignment;
+ lta->long_alignment = msg->long_alignment;
+ lta->byte_order = msg->byte_order;
+
+ lta->v_major = msg->major;
+ lta->v_minor = msg->minor;
+ lta->sessions = lttng_ht_new(0, LTTNG_HT_TYPE_U64);
+ lta->ust_objd = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
+ lta->notify_sock = -1;
+
+ /* Copy name and make sure it's NULL terminated. */
+ strncpy(lta->name, msg->name, sizeof(lta->name));
+ lta->name[UST_APP_PROCNAME_LEN] = '\0';
+
+ /*
+ * Before this can be called, when receiving the registration information,
+ * the application compatibility is checked. So, at this point, the
+ * application can work with this session daemon.
+ */
+ lta->compatible = 1;
+
+ lta->pid = msg->pid;
+ lttng_ht_node_init_ulong(<a->pid_n, (unsigned long) lta->pid);
+ lta->sock = sock;
+ lttng_ht_node_init_ulong(<a->sock_n, (unsigned long) lta->sock);
+
+ CDS_INIT_LIST_HEAD(<a->teardown_head);
+
+error:
+ return lta;
+}
+
+/*
+ * For a given application object, add it to every hash table.
+ */
+void ust_app_add(struct ust_app *app)
+{
+ assert(app);
+ assert(app->notify_sock >= 0);
+
+ rcu_read_lock();
+
+ /*
+ * On a re-registration, we want to kick out the previous registration of
+ * that pid
+ */
+ lttng_ht_add_replace_ulong(ust_app_ht, &app->pid_n);
+
+ /*
+ * The socket _should_ be unique until _we_ call close. So, a add_unique
+ * for the ust_app_ht_by_sock is used which asserts fail if the entry was
+ * already in the table.
+ */
+ lttng_ht_add_unique_ulong(ust_app_ht_by_sock, &app->sock_n);
+
+ /* Add application to the notify socket hash table. */
+ lttng_ht_node_init_ulong(&app->notify_sock_n, app->notify_sock);
+ lttng_ht_add_unique_ulong(ust_app_ht_by_notify_sock, &app->notify_sock_n);
+
+ DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s "
+ "notify_sock:%d (version %d.%d)", app->pid, app->ppid, app->uid,
+ app->gid, app->sock, app->name, app->notify_sock, app->v_major,
+ app->v_minor);
+
+ rcu_read_unlock();
+}
+
+/*
+ * Set the application version into the object.
+ *
+ * Return 0 on success else a negative value either an errno code or a
+ * LTTng-UST error code.
+ */
+int ust_app_version(struct ust_app *app)
+{
+ int ret;
+
+ assert(app);
+
+ ret = ustctl_tracer_version(app->sock, &app->version);
+ if (ret < 0) {
+ if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
+ ERR("UST app %d verson failed with ret %d", app->sock, ret);
+ } else {
+ DBG3("UST app %d verion failed. Application is dead", app->sock);
+ }
+ }
+
+ 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.
+ */
+void ust_app_unregister(int sock)
+{
+ struct ust_app *lta;
+ struct lttng_ht_node_ulong *node;
+ struct lttng_ht_iter iter;
+ struct ust_app_session *ua_sess;
+ int ret;
+
+ rcu_read_lock();
+
+ /* Get the node reference for a call_rcu */
+ lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &iter);
+ node = lttng_ht_iter_get_node_ulong(&iter);
+ assert(node);
+
+ lta = caa_container_of(node, struct ust_app, sock_n);