* was written and a negative value on error.
*/
int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
- struct channel *chan)
+ struct channel *chan, bool *coherent)
{
struct lib_ring_buffer_ctx ctx;
int ret = 0;
ret = stream->transport->ops.event_reserve(&ctx, 0);
if (ret != 0) {
printk(KERN_WARNING "LTTng: Metadata event reservation failed\n");
+ stream->coherent = false;
goto end;
}
stream->transport->ops.event_write(&ctx,
reserve_len);
stream->transport->ops.event_commit(&ctx);
stream->metadata_in += reserve_len;
+ if (reserve_len < len || stream->metadata_cache->producing != 0)
+ stream->coherent = false;
+ else
+ stream->coherent = true;
ret = reserve_len;
end:
+ if (coherent)
+ *coherent = stream->coherent;
mutex_unlock(&stream->metadata_cache->lock);
return ret;
}
+static
+void lttng_metadata_begin(struct lttng_session *session)
+{
+ mutex_lock(&session->metadata_cache->lock);
+ session->metadata_cache->producing++;
+ mutex_unlock(&session->metadata_cache->lock);
+}
+
+static
+void lttng_metadata_end(struct lttng_session *session)
+{
+ mutex_lock(&session->metadata_cache->lock);
+ WARN_ON_ONCE(!session->metadata_cache->producing);
+ session->metadata_cache->producing--;
+ mutex_unlock(&session->metadata_cache->lock);
+}
+
/*
* Write the metadata to the metadata cache.
* Must be called with sessions_mutex held.
* The metadata cache lock protects us from concurrent read access from
* thread outputting metadata content to ring buffer.
+ * The content of the printf is printed as a single atomic metadata
+ * transaction.
*/
int lttng_metadata_printf(struct lttng_session *session,
const char *fmt, ...)
len = strlen(str);
mutex_lock(&session->metadata_cache->lock);
+ session->metadata_cache->producing++;
if (session->metadata_cache->metadata_written + len >
session->metadata_cache->cache_alloc) {
char *tmp_cache_realloc;
session->metadata_cache->metadata_written,
str, len);
session->metadata_cache->metadata_written += len;
+ session->metadata_cache->producing--;
mutex_unlock(&session->metadata_cache->lock);
kfree(str);
return 0;
err:
+ session->metadata_cache->producing--;
mutex_unlock(&session->metadata_cache->lock);
kfree(str);
return -ENOMEM;
/*
* Must be called with sessions_mutex held.
+ * The entire event metadata is printed as a single atomic metadata
+ * transaction.
*/
static
int _lttng_event_metadata_statedump(struct lttng_session *session,
if (chan->channel_type == METADATA_CHANNEL)
return 0;
+ lttng_metadata_begin(session);
+
ret = lttng_metadata_printf(session,
"event {\n"
" name = \"%s\";\n"
event->metadata_dumped = 1;
end:
+ lttng_metadata_end(session);
return ret;
}
/*
* Must be called with sessions_mutex held.
+ * The entire channel metadata is printed as a single atomic metadata
+ * transaction.
*/
static
int _lttng_channel_metadata_statedump(struct lttng_session *session,
if (chan->channel_type == METADATA_CHANNEL)
return 0;
+ lttng_metadata_begin(session);
+
WARN_ON_ONCE(!chan->header_type);
ret = lttng_metadata_printf(session,
"stream {\n"
chan->metadata_dumped = 1;
end:
+ lttng_metadata_end(session);
return ret;
}
if (!READ_ONCE(session->active))
return 0;
+
+ lttng_metadata_begin(session);
+
if (session->metadata_dumped)
goto skip_session;
}
session->metadata_dumped = 1;
end:
+ lttng_metadata_end(session);
return ret;
}