+end_nosignal:
+ /*
+ * Return 1 to indicate success since the 0 value can be a socket
+ * shutdown during the recv() or send() call.
+ */
+ ret_func = 1;
+ goto end;
+error_fatal:
+ /* This will issue a consumer stop. */
+ ret_func = -1;
+ goto end;
+end_msg_sessiond:
+ /*
+ * The returned value here is not useful since either way we'll return 1 to
+ * the caller because the session daemon socket management is done
+ * elsewhere. Returning a negative code or 0 will shutdown the consumer.
+ */
+ {
+ int ret_send_status;
+
+ ret_send_status = consumer_send_status_msg(sock, ret_code);
+ if (ret_send_status < 0) {
+ goto error_fatal;
+ }
+ }
+
+ ret_func = 1;
+
+end:
+ health_code_update();
+ rcu_read_unlock();
+ return ret_func;
+}
+
+/*
+ * Sync metadata meaning request them to the session daemon and snapshot to the
+ * metadata thread can consumer them.
+ *
+ * Metadata stream lock MUST be acquired.
+ */
+enum sync_metadata_status lttng_kconsumer_sync_metadata(
+ struct lttng_consumer_stream *metadata)
+{
+ int ret;
+ enum sync_metadata_status status;
+
+ assert(metadata);
+
+ ret = kernctl_buffer_flush(metadata->wait_fd);
+ if (ret < 0) {
+ ERR("Failed to flush kernel stream");
+ status = SYNC_METADATA_STATUS_ERROR;
+ goto end;
+ }
+
+ ret = kernctl_snapshot(metadata->wait_fd);
+ if (ret < 0) {
+ if (errno == EAGAIN) {
+ /* No new metadata, exit. */
+ DBG("Sync metadata, no new kernel metadata");
+ status = SYNC_METADATA_STATUS_NO_DATA;
+ } else {
+ ERR("Sync metadata, taking kernel snapshot failed.");
+ status = SYNC_METADATA_STATUS_ERROR;
+ }
+ } else {
+ status = SYNC_METADATA_STATUS_NEW_DATA;
+ }
+
+end:
+ return status;
+}
+
+static
+int extract_common_subbuffer_info(struct lttng_consumer_stream *stream,
+ struct stream_subbuffer *subbuf)
+{
+ int ret;
+
+ ret = kernctl_get_subbuf_size(
+ stream->wait_fd, &subbuf->info.data.subbuf_size);
+ if (ret) {
+ goto end;
+ }
+
+ ret = kernctl_get_padded_subbuf_size(
+ stream->wait_fd, &subbuf->info.data.padded_subbuf_size);
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int extract_metadata_subbuffer_info(struct lttng_consumer_stream *stream,
+ struct stream_subbuffer *subbuf)
+{
+ int ret;
+
+ ret = extract_common_subbuffer_info(stream, subbuf);
+ if (ret) {
+ goto end;
+ }
+
+ ret = kernctl_get_metadata_version(
+ stream->wait_fd, &subbuf->info.metadata.version);
+ if (ret) {
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int extract_data_subbuffer_info(struct lttng_consumer_stream *stream,
+ struct stream_subbuffer *subbuf)
+{
+ int ret;
+
+ ret = extract_common_subbuffer_info(stream, subbuf);
+ if (ret) {
+ goto end;
+ }
+
+ ret = kernctl_get_packet_size(
+ stream->wait_fd, &subbuf->info.data.packet_size);
+ if (ret < 0) {
+ PERROR("Failed to get sub-buffer packet size");
+ goto end;
+ }
+
+ ret = kernctl_get_content_size(
+ stream->wait_fd, &subbuf->info.data.content_size);
+ if (ret < 0) {
+ PERROR("Failed to get sub-buffer content size");
+ goto end;
+ }
+
+ ret = kernctl_get_timestamp_begin(
+ stream->wait_fd, &subbuf->info.data.timestamp_begin);
+ if (ret < 0) {
+ PERROR("Failed to get sub-buffer begin timestamp");
+ goto end;
+ }
+
+ ret = kernctl_get_timestamp_end(
+ stream->wait_fd, &subbuf->info.data.timestamp_end);
+ if (ret < 0) {
+ PERROR("Failed to get sub-buffer end timestamp");
+ goto end;
+ }
+
+ ret = kernctl_get_events_discarded(
+ stream->wait_fd, &subbuf->info.data.events_discarded);
+ if (ret) {
+ PERROR("Failed to get sub-buffer events discarded count");
+ goto end;
+ }
+
+ ret = kernctl_get_sequence_number(stream->wait_fd,
+ &subbuf->info.data.sequence_number.value);
+ if (ret) {
+ /* May not be supported by older LTTng-modules. */
+ if (ret != -ENOTTY) {
+ PERROR("Failed to get sub-buffer sequence number");
+ goto end;