+/*
+ * Create stream onto the UST tracer for a given channel.
+ *
+ * Return -ENOENT if no more stream is available for this channel.
+ * On success, return 0.
+ * On error, return a negative value.
+ */
+static int create_ust_stream(struct ust_app *app,
+ struct ust_app_channel *ua_chan, struct ust_app_stream *stream)
+{
+ int ret;
+
+ assert(app);
+ assert(ua_chan);
+ assert(ua_chan->obj);
+ assert(stream);
+
+ health_code_update(&health_thread_cmd);
+
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD on stream creation");
+ /* Just to make sure we never return -ENOENT. */
+ ret = -1;
+ goto error;
+ }
+
+ /*
+ * Set the stream name before creating it. On error, we don't have to
+ * delete it on the tracer side.
+ */
+ ret = snprintf(stream->name, sizeof(stream->name), "%s_%u",
+ ua_chan->name, ua_chan->streams.count);
+ if (ret < 0) {
+ /* Without the stream name we can't continue using it. */
+ PERROR("snprintf UST create stream");
+ /* Just to make sure we never return -ENOENT. */
+ ret = -1;
+ goto error;
+ }
+
+ ret = ustctl_create_stream(app->sock, ua_chan->obj, &stream->obj);
+ if (ret < 0) {
+ lttng_fd_put(LTTNG_FD_APPS, 2);
+ /* Indicates that there is no more stream for that channel. */
+ if (ret != -LTTNG_UST_ERR_NOENT) {
+ ERR("UST create metadata stream failed (ret: %d)", ret);
+ }
+ goto error;
+ }
+
+ /* Set stream handle with the returned value. */
+ stream->handle = stream->obj->handle;
+
+error:
+ health_code_update(&health_thread_cmd);
+ return ret;
+}
+