+ switch (usess->buffer_type) {
+ case LTTNG_BUFFER_PER_PID:
+ /* Init local registry. */
+ ret = setup_buffer_reg_pid(ua_sess, app, NULL);
+ if (ret < 0) {
+ goto error;
+ }
+ break;
+ case LTTNG_BUFFER_PER_UID:
+ /* Look for a global registry. If none exists, create one. */
+ ret = setup_buffer_reg_uid(usess, app, NULL);
+ if (ret < 0) {
+ goto error;
+ }
+ break;
+ default:
+ assert(0);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ health_code_update();
+
+ if (ua_sess->handle == -1) {
+ ret = ustctl_create_session(app->sock);
+ if (ret < 0) {
+ if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+ ERR("Creating session for app pid %d with ret %d",
+ app->pid, ret);
+ } else {
+ DBG("UST app creating session failed. Application is dead");
+ /*
+ * This is normal behavior, an application can die during the
+ * creation process. Don't report an error so the execution can
+ * continue normally. This will get flagged ENOTCONN and the
+ * caller will handle it.
+ */
+ ret = 0;
+ }
+ delete_ust_app_session(-1, ua_sess, app);
+ if (ret != -ENOMEM) {
+ /*
+ * Tracer is probably gone or got an internal error so let's
+ * behave like it will soon unregister or not usable.
+ */
+ ret = -ENOTCONN;
+ }
+ goto error;
+ }
+
+ ua_sess->handle = ret;
+
+ /* Add ust app session to app's HT */
+ lttng_ht_node_init_u64(&ua_sess->node,
+ ua_sess->tracing_id);
+ lttng_ht_add_unique_u64(app->sessions, &ua_sess->node);
+
+ DBG2("UST app session created successfully with handle %d", ret);
+ }
+
+ *ua_sess_ptr = ua_sess;
+ if (is_created) {
+ *is_created = created;
+ }
+
+ /* Everything went well. */
+ ret = 0;
+
+error:
+ health_code_update();
+ return ret;
+}
+
+/*
+ * Create a context for the channel on the tracer.
+ *
+ * Called with UST app session lock held and a RCU read side lock.
+ */
+static
+int create_ust_app_channel_context(struct ust_app_session *ua_sess,
+ struct ust_app_channel *ua_chan, struct lttng_ust_context *uctx,
+ struct ust_app *app)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter;
+ struct lttng_ht_node_ulong *node;
+ struct ust_app_ctx *ua_ctx;
+
+ DBG2("UST app adding context to channel %s", ua_chan->name);
+
+ lttng_ht_lookup(ua_chan->ctx, (void *)((unsigned long)uctx->ctx), &iter);
+ node = lttng_ht_iter_get_node_ulong(&iter);
+ if (node != NULL) {
+ ret = -EEXIST;
+ goto error;
+ }
+
+ ua_ctx = alloc_ust_app_ctx(uctx);
+ if (ua_ctx == NULL) {
+ /* malloc failed */
+ ret = -1;
+ goto error;
+ }
+
+ lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx);
+ lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node);
+ cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
+
+ ret = create_ust_channel_context(ua_chan, ua_ctx, app);
+ if (ret < 0) {
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * Enable on the tracer side a ust app event for the session and channel.
+ *
+ * Called with UST app session lock held.
+ */
+static
+int enable_ust_app_event(struct ust_app_session *ua_sess,
+ struct ust_app_event *ua_event, struct ust_app *app)
+{
+ int ret;
+
+ ret = enable_ust_event(app, ua_sess, ua_event);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ua_event->enabled = 1;
+
+error:
+ return ret;
+}
+
+/*
+ * Disable on the tracer side a ust app event for the session and channel.
+ */
+static int disable_ust_app_event(struct ust_app_session *ua_sess,
+ struct ust_app_event *ua_event, struct ust_app *app)
+{
+ int ret;
+
+ ret = disable_ust_event(app, ua_sess, ua_event);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ua_event->enabled = 0;
+
+error:
+ return ret;
+}
+
+/*
+ * Lookup ust app channel for session and disable it on the tracer side.
+ */
+static
+int disable_ust_app_channel(struct ust_app_session *ua_sess,
+ struct ust_app_channel *ua_chan, struct ust_app *app)
+{
+ int ret;
+
+ ret = disable_ust_channel(app, ua_sess, ua_chan);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ua_chan->enabled = 0;
+
+error:
+ return ret;
+}
+
+/*
+ * Lookup ust app channel for session and enable it on the tracer side. This
+ * MUST be called with a RCU read side lock acquired.
+ */
+static int enable_ust_app_channel(struct ust_app_session *ua_sess,
+ struct ltt_ust_channel *uchan, struct ust_app *app)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter;
+ struct lttng_ht_node_str *ua_chan_node;
+ struct ust_app_channel *ua_chan;
+
+ lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
+ ua_chan_node = lttng_ht_iter_get_node_str(&iter);
+ if (ua_chan_node == NULL) {
+ DBG2("Unable to find channel %s in ust session id %" PRIu64,
+ uchan->name, ua_sess->tracing_id);
+ goto error;
+ }
+
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+
+ ret = enable_ust_channel(app, ua_sess, ua_chan);
+ if (ret < 0) {
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * Ask the consumer to create a channel and get it if successful.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static int do_consumer_create_channel(struct ltt_ust_session *usess,
+ struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
+ int bitness, struct ust_registry_session *registry)
+{
+ int ret;
+ unsigned int nb_fd = 0;
+ struct consumer_socket *socket;
+
+ assert(usess);
+ assert(ua_sess);
+ assert(ua_chan);
+ assert(registry);
+
+ rcu_read_lock();
+ health_code_update();
+
+ /* Get the right consumer socket for the application. */
+ socket = consumer_find_socket_by_bitness(bitness, usess->consumer);
+ if (!socket) {
+ ret = -EINVAL;
+ goto error;
+ }
+
+ health_code_update();
+
+ /* 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 channel");
+ goto error;
+ }
+
+ /*
+ * Ask consumer to create channel. The consumer will return the number of
+ * stream we have to expect.
+ */
+ ret = ust_consumer_ask_channel(ua_sess, ua_chan, usess->consumer, socket,
+ registry);
+ if (ret < 0) {
+ goto error_ask;
+ }
+
+ /*
+ * Compute the number of fd needed before receiving them. It must be 2 per
+ * stream (2 being the default value here).
+ */
+ nb_fd = DEFAULT_UST_STREAM_FD_NUM * ua_chan->expected_stream_count;
+
+ /* Reserve the amount of file descriptor we need. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, nb_fd);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon create channel");
+ goto error_fd_get_stream;
+ }
+
+ health_code_update();
+
+ /*
+ * Now get the channel from the consumer. This call wil populate the stream
+ * list of that channel and set the ust objects.
+ */
+ if (usess->consumer->enabled) {
+ ret = ust_consumer_get_channel(socket, ua_chan);
+ if (ret < 0) {
+ goto error_destroy;
+ }
+ }
+
+ rcu_read_unlock();
+ return 0;
+
+error_destroy:
+ lttng_fd_put(LTTNG_FD_APPS, nb_fd);
+error_fd_get_stream:
+ /*
+ * Initiate a destroy channel on the consumer since we had an error
+ * handling it on our side. The return value is of no importance since we
+ * already have a ret value set by the previous error that we need to
+ * return.
+ */
+ (void) ust_consumer_destroy_channel(socket, ua_chan);
+error_ask:
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+error:
+ health_code_update();
+ rcu_read_unlock();
+ return ret;
+}
+
+/*
+ * Duplicate the ust data object of the ust app stream and save it in the
+ * buffer registry stream.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static int duplicate_stream_object(struct buffer_reg_stream *reg_stream,
+ struct ust_app_stream *stream)
+{
+ int ret;
+
+ assert(reg_stream);
+ assert(stream);
+
+ /* Reserve the amount of file descriptor we need. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon duplicate stream");
+ goto error;
+ }
+
+ /* Duplicate object for stream once the original is in the registry. */
+ ret = ustctl_duplicate_ust_object_data(&stream->obj,
+ reg_stream->obj.ust);
+ if (ret < 0) {
+ ERR("Duplicate stream obj from %p to %p failed with ret %d",
+ reg_stream->obj.ust, stream->obj, ret);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
+ goto error;
+ }
+ stream->handle = stream->obj->handle;
+
+error:
+ return ret;
+}
+
+/*
+ * Duplicate the ust data object of the ust app. channel and save it in the
+ * buffer registry channel.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static int duplicate_channel_object(struct buffer_reg_channel *reg_chan,
+ struct ust_app_channel *ua_chan)
+{
+ int ret;
+
+ assert(reg_chan);
+ assert(ua_chan);
+
+ /* Need two fds for the channel. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 1);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon duplicate channel");
+ goto error_fd_get;
+ }
+
+ /* Duplicate object for stream once the original is in the registry. */
+ ret = ustctl_duplicate_ust_object_data(&ua_chan->obj, reg_chan->obj.ust);
+ if (ret < 0) {
+ ERR("Duplicate channel obj from %p to %p failed with ret: %d",
+ reg_chan->obj.ust, ua_chan->obj, ret);
+ goto error;
+ }
+ ua_chan->handle = ua_chan->obj->handle;
+
+ return 0;
+
+error:
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+error_fd_get:
+ return ret;
+}
+
+/*
+ * For a given channel buffer registry, setup all streams of the given ust
+ * application channel.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static int setup_buffer_reg_streams(struct buffer_reg_channel *reg_chan,
+ struct ust_app_channel *ua_chan)
+{
+ int ret = 0;
+ struct ust_app_stream *stream, *stmp;
+
+ assert(reg_chan);
+ assert(ua_chan);