+ new_stream->chan = channel;
+ new_stream->wait_fd = fd;
+ consumer_stream_update_channel_attributes(new_stream,
+ channel);
+ switch (channel->output) {
+ case CONSUMER_CHANNEL_SPLICE:
+ new_stream->output = LTTNG_EVENT_SPLICE;
+ ret = utils_create_pipe(new_stream->splice_pipe);
+ if (ret < 0) {
+ goto end_nosignal;
+ }
+ break;
+ case CONSUMER_CHANNEL_MMAP:
+ new_stream->output = LTTNG_EVENT_MMAP;
+ break;
+ default:
+ ERR("Stream output unknown %d", channel->output);
+ goto end_nosignal;
+ }
+
+ /*
+ * We've just assigned the channel to the stream so increment the
+ * refcount right now. We don't need to increment the refcount for
+ * streams in no monitor because we handle manually the cleanup of
+ * those. It is very important to make sure there is NO prior
+ * consumer_del_stream() calls or else the refcount will be unbalanced.
+ */
+ if (channel->monitor) {
+ uatomic_inc(&new_stream->chan->refcount);
+ }
+
+ /*
+ * The buffer flush is done on the session daemon side for the kernel
+ * so no need for the stream "hangup_flush_done" variable to be
+ * tracked. This is important for a kernel stream since we don't rely
+ * on the flush state of the stream to read data. It's not the case for
+ * user space tracing.
+ */
+ new_stream->hangup_flush_done = 0;
+
+ health_code_update();
+
+ if (ctx->on_recv_stream) {
+ ret = ctx->on_recv_stream(new_stream);
+ if (ret < 0) {
+ consumer_stream_free(new_stream);
+ goto end_nosignal;
+ }
+ }
+
+ health_code_update();
+
+ if (new_stream->metadata_flag) {
+ channel->metadata_stream = new_stream;
+ }
+
+ /* Do not monitor this stream. */
+ if (!channel->monitor) {
+ DBG("Kernel consumer add stream %s in no monitor mode with "
+ "relayd id %" PRIu64, new_stream->name,
+ new_stream->net_seq_idx);
+ cds_list_add(&new_stream->send_node, &channel->streams.head);
+ break;
+ }
+
+ /* Send stream to relayd if the stream has an ID. */
+ if (new_stream->net_seq_idx != (uint64_t) -1ULL) {
+ ret = consumer_send_relayd_stream(new_stream,
+ new_stream->chan->pathname);
+ if (ret < 0) {
+ consumer_stream_free(new_stream);
+ goto end_nosignal;
+ }
+
+ /*
+ * If adding an extra stream to an already
+ * existing channel (e.g. cpu hotplug), we need
+ * to send the "streams_sent" command to relayd.
+ */
+ if (channel->streams_sent_to_relayd) {
+ ret = consumer_send_relayd_streams_sent(
+ new_stream->net_seq_idx);
+ if (ret < 0) {
+ goto end_nosignal;
+ }
+ }
+ }
+
+ /* Get the right pipe where the stream will be sent. */
+ if (new_stream->metadata_flag) {
+ consumer_add_metadata_stream(new_stream);
+ stream_pipe = ctx->consumer_metadata_pipe;
+ } else {
+ consumer_add_data_stream(new_stream);
+ stream_pipe = ctx->consumer_data_pipe;
+ }
+
+ /* Visible to other threads */
+ new_stream->globally_visible = 1;
+
+ health_code_update();
+
+ ret = lttng_pipe_write(stream_pipe, &new_stream, sizeof(new_stream));
+ if (ret < 0) {
+ ERR("Consumer write %s stream to pipe %d",
+ new_stream->metadata_flag ? "metadata" : "data",
+ lttng_pipe_get_writefd(stream_pipe));
+ if (new_stream->metadata_flag) {
+ consumer_del_stream_for_metadata(new_stream);
+ } else {
+ consumer_del_stream_for_data(new_stream);
+ }
+ goto end_nosignal;
+ }
+
+ DBG("Kernel consumer ADD_STREAM %s (fd: %d) %s with relayd id %" PRIu64,
+ new_stream->name, fd, new_stream->chan->pathname, new_stream->relayd_stream_id);
+ break;
+ }
+ case LTTNG_CONSUMER_STREAMS_SENT:
+ {
+ struct lttng_consumer_channel *channel;
+
+ /*
+ * Get stream's channel reference. Needed when adding the stream to the
+ * global hash table.
+ */
+ channel = consumer_find_channel(msg.u.sent_streams.channel_key);
+ if (!channel) {
+ /*
+ * We could not find the channel. Can happen if cpu hotplug
+ * happens while tearing down.
+ */
+ ERR("Unable to find channel key %" PRIu64,
+ msg.u.sent_streams.channel_key);
+ ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND;
+ }
+
+ health_code_update();
+
+ /*
+ * Send status code to session daemon.
+ */
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0 || ret_code != LTTCOMM_CONSUMERD_SUCCESS) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto end_nosignal;
+ }
+
+ health_code_update();
+
+ /*
+ * We should not send this message if we don't monitor the
+ * streams in this channel.
+ */
+ if (!channel->monitor) {
+ break;
+ }
+
+ health_code_update();
+ /* Send stream to relayd if the stream has an ID. */
+ if (msg.u.sent_streams.net_seq_idx != (uint64_t) -1ULL) {
+ ret = consumer_send_relayd_streams_sent(
+ msg.u.sent_streams.net_seq_idx);
+ if (ret < 0) {
+ goto end_nosignal;
+ }
+ channel->streams_sent_to_relayd = true;
+ }
+ break;
+ }
+ case LTTNG_CONSUMER_UPDATE_STREAM:
+ {
+ rcu_read_unlock();
+ return -ENOSYS;
+ }
+ case LTTNG_CONSUMER_DESTROY_RELAYD:
+ {
+ uint64_t index = msg.u.destroy_relayd.net_seq_idx;
+ struct consumer_relayd_sock_pair *relayd;
+
+ DBG("Kernel consumer destroying relayd %" PRIu64, index);
+
+ /* Get relayd reference if exists. */
+ relayd = consumer_find_relayd(index);
+ if (relayd == NULL) {
+ DBG("Unable to find relayd %" PRIu64, index);
+ ret_code = LTTCOMM_CONSUMERD_RELAYD_FAIL;
+ }
+
+ /*
+ * Each relayd socket pair has a refcount of stream attached to it
+ * which tells if the relayd is still active or not depending on the
+ * refcount value.
+ *
+ * This will set the destroy flag of the relayd object and destroy it
+ * if the refcount reaches zero when called.
+ *
+ * The destroy can happen either here or when a stream fd hangs up.
+ */
+ if (relayd) {
+ consumer_flag_relayd_for_destroy(relayd);
+ }
+
+ health_code_update();
+
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto error_fatal;
+ }
+
+ goto end_nosignal;
+ }
+ case LTTNG_CONSUMER_DATA_PENDING:
+ {
+ int32_t ret;
+ uint64_t id = msg.u.data_pending.session_id;
+
+ DBG("Kernel consumer data pending command for id %" PRIu64, id);
+
+ ret = consumer_data_pending(id);
+
+ health_code_update();
+
+ /* Send back returned value to session daemon */
+ ret = lttcomm_send_unix_sock(sock, &ret, sizeof(ret));
+ if (ret < 0) {
+ PERROR("send data pending ret code");
+ goto error_fatal;
+ }
+
+ /*
+ * No need to send back a status message since the data pending
+ * returned value is the response.
+ */
+ break;
+ }
+ case LTTNG_CONSUMER_SNAPSHOT_CHANNEL:
+ {
+ if (msg.u.snapshot_channel.metadata == 1) {
+ ret = lttng_kconsumer_snapshot_metadata(msg.u.snapshot_channel.key,
+ msg.u.snapshot_channel.pathname,
+ msg.u.snapshot_channel.relayd_id, ctx);
+ if (ret < 0) {
+ ERR("Snapshot metadata failed");
+ ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA;
+ }
+ } else {
+ ret = lttng_kconsumer_snapshot_channel(msg.u.snapshot_channel.key,
+ msg.u.snapshot_channel.pathname,
+ msg.u.snapshot_channel.relayd_id,
+ msg.u.snapshot_channel.nb_packets_per_stream,
+ ctx);
+ if (ret < 0) {
+ ERR("Snapshot channel failed");
+ ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND;
+ }
+ }
+
+ health_code_update();
+
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto end_nosignal;
+ }
+ break;
+ }
+ case LTTNG_CONSUMER_DESTROY_CHANNEL:
+ {
+ uint64_t key = msg.u.destroy_channel.key;
+ struct lttng_consumer_channel *channel;
+
+ channel = consumer_find_channel(key);
+ if (!channel) {
+ ERR("Kernel consumer destroy channel %" PRIu64 " not found", key);
+ ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND;
+ }
+
+ health_code_update();
+
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto end_nosignal;
+ }
+
+ health_code_update();
+
+ /* Stop right now if no channel was found. */
+ if (!channel) {
+ goto end_nosignal;
+ }
+
+ /*
+ * This command should ONLY be issued for channel with streams set in
+ * no monitor mode.
+ */
+ assert(!channel->monitor);
+
+ /*
+ * The refcount should ALWAYS be 0 in the case of a channel in no
+ * monitor mode.
+ */
+ assert(!uatomic_sub_return(&channel->refcount, 1));
+
+ consumer_del_channel(channel);
+
+ goto end_nosignal;
+ }
+ case LTTNG_CONSUMER_DISCARDED_EVENTS:
+ {
+ ssize_t ret;
+ uint64_t count;
+ struct lttng_consumer_channel *channel;
+ uint64_t id = msg.u.discarded_events.session_id;
+ uint64_t key = msg.u.discarded_events.channel_key;
+
+ DBG("Kernel consumer discarded events command for session id %"
+ PRIu64 ", channel key %" PRIu64, id, key);
+
+ channel = consumer_find_channel(key);
+ if (!channel) {
+ ERR("Kernel consumer discarded events channel %"
+ PRIu64 " not found", key);
+ count = 0;
+ } else {
+ count = channel->discarded_events;
+ }
+
+ health_code_update();
+
+ /* Send back returned value to session daemon */
+ ret = lttcomm_send_unix_sock(sock, &count, sizeof(count));
+ if (ret < 0) {
+ PERROR("send discarded events");
+ goto error_fatal;
+ }
+
+ break;
+ }
+ case LTTNG_CONSUMER_LOST_PACKETS:
+ {
+ ssize_t ret;
+ uint64_t count;
+ struct lttng_consumer_channel *channel;
+ uint64_t id = msg.u.lost_packets.session_id;
+ uint64_t key = msg.u.lost_packets.channel_key;
+
+ DBG("Kernel consumer lost packets command for session id %"
+ PRIu64 ", channel key %" PRIu64, id, key);
+
+ channel = consumer_find_channel(key);
+ if (!channel) {
+ ERR("Kernel consumer lost packets channel %"
+ PRIu64 " not found", key);
+ count = 0;
+ } else {
+ count = channel->lost_packets;
+ }
+
+ health_code_update();
+
+ /* Send back returned value to session daemon */
+ ret = lttcomm_send_unix_sock(sock, &count, sizeof(count));
+ if (ret < 0) {
+ PERROR("send lost packets");
+ goto error_fatal;
+ }
+
+ break;
+ }
+ case LTTNG_CONSUMER_SET_CHANNEL_MONITOR_PIPE:
+ {
+ int channel_monitor_pipe;
+
+ ret_code = LTTCOMM_CONSUMERD_SUCCESS;
+ /* Successfully received the command's type. */
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ goto error_fatal;
+ }
+
+ ret = lttcomm_recv_fds_unix_sock(sock, &channel_monitor_pipe,
+ 1);
+ if (ret != sizeof(channel_monitor_pipe)) {
+ ERR("Failed to receive channel monitor pipe");
+ goto error_fatal;
+ }
+
+ DBG("Received channel monitor pipe (%d)", channel_monitor_pipe);
+ ret = consumer_timer_thread_set_channel_monitor_pipe(
+ channel_monitor_pipe);
+ if (!ret) {
+ int flags;
+
+ ret_code = LTTCOMM_CONSUMERD_SUCCESS;
+ /* Set the pipe as non-blocking. */
+ ret = fcntl(channel_monitor_pipe, F_GETFL, 0);
+ if (ret == -1) {
+ PERROR("fcntl get flags of the channel monitoring pipe");
+ goto error_fatal;
+ }
+ flags = ret;
+
+ ret = fcntl(channel_monitor_pipe, F_SETFL,
+ flags | O_NONBLOCK);
+ if (ret == -1) {
+ PERROR("fcntl set O_NONBLOCK flag of the channel monitoring pipe");
+ goto error_fatal;
+ }
+ DBG("Channel monitor pipe set as non-blocking");
+ } else {
+ ret_code = LTTCOMM_CONSUMERD_ALREADY_SET;
+ }
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ goto error_fatal;
+ }
+ break;
+ }
+ case LTTNG_CONSUMER_SET_CHANNEL_ROTATE_PIPE:
+ {
+ int channel_rotate_pipe;
+ int flags;
+
+ ret_code = LTTCOMM_CONSUMERD_SUCCESS;
+ /* Successfully received the command's type. */
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ goto error_fatal;
+ }
+
+ ret = lttcomm_recv_fds_unix_sock(sock, &channel_rotate_pipe, 1);
+ if (ret != (ssize_t) sizeof(channel_rotate_pipe)) {
+ ERR("Failed to receive channel rotate pipe");
+ goto error_fatal;
+ }
+
+ DBG("Received channel rotate pipe (%d)", channel_rotate_pipe);
+ ctx->channel_rotate_pipe = channel_rotate_pipe;
+ /* Set the pipe as non-blocking. */
+ ret = fcntl(channel_rotate_pipe, F_GETFL, 0);
+ if (ret == -1) {
+ PERROR("fcntl get flags of the channel rotate pipe");
+ goto error_fatal;
+ }
+ flags = ret;
+
+ ret = fcntl(channel_rotate_pipe, F_SETFL, flags | O_NONBLOCK);
+ if (ret == -1) {
+ PERROR("fcntl set O_NONBLOCK flag of the channel rotate pipe");
+ goto error_fatal;
+ }
+ DBG("Channel rotate pipe set as non-blocking");
+ ret_code = LTTCOMM_CONSUMERD_SUCCESS;
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ goto error_fatal;
+ }
+ break;
+ }
+ case LTTNG_CONSUMER_ROTATE_CHANNEL:
+ {
+ DBG("Consumer rotate channel %" PRIu64, msg.u.rotate_channel.key);
+