BUG_ON(chan->channel_type == METADATA_CHANNEL);
_lttng_channel_destroy(chan);
}
+ mutex_lock(&session->metadata_cache->lock);
list_for_each_entry(metadata_stream, &session->metadata_cache->metadata_stream, list)
_lttng_metadata_channel_hangup(metadata_stream);
+ mutex_unlock(&session->metadata_cache->lock);
lttng_id_tracker_destroy(&session->pid_tracker, false);
lttng_id_tracker_destroy(&session->vpid_tracker, false);
lttng_id_tracker_destroy(&session->uid_tracker, false);
goto active; /* Refuse to add channel to active session */
transport = lttng_transport_find(transport_name);
if (!transport) {
- printk(KERN_WARNING "LTTng transport %s not found\n",
+ printk(KERN_WARNING "LTTng: transport %s not found\n",
transport_name);
goto notransport;
}
if (!try_module_get(transport->owner)) {
- printk(KERN_WARNING "LTT : Can't lock transport module.\n");
+ printk(KERN_WARNING "LTTng: Can't lock transport module.\n");
goto notransport;
}
chan = kzalloc(sizeof(struct lttng_channel), GFP_KERNEL);
NULL, NULL, desc,
LTTNG_KERNEL_TRACEPOINT);
if (!event) {
- printk(KERN_INFO "Unable to create event %s\n",
+ printk(KERN_INFO "LTTng: Unable to create event %s\n",
probe_desc->event_desc[i]->name);
}
}
* 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->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)
+{
+ if (atomic_inc_return(&session->metadata_cache->producing) == 1)
+ mutex_lock(&session->metadata_cache->lock);
+}
+
+static
+void lttng_metadata_end(struct lttng_session *session)
+{
+ WARN_ON_ONCE(!atomic_read(&session->metadata_cache->producing));
+ if (atomic_dec_return(&session->metadata_cache->producing) == 0) {
+ struct lttng_metadata_stream *stream;
+
+ list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list)
+ wake_up_interruptible(&stream->read_wait);
+ 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, ...)
char *str;
size_t len;
va_list ap;
- struct lttng_metadata_stream *stream;
WARN_ON_ONCE(!READ_ONCE(session->active));
return -ENOMEM;
len = strlen(str);
- mutex_lock(&session->metadata_cache->lock);
+ WARN_ON_ONCE(!atomic_read(&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;
- mutex_unlock(&session->metadata_cache->lock);
kfree(str);
- list_for_each_entry(stream, &session->metadata_cache->metadata_stream, list)
- wake_up_interruptible(&stream->read_wait);
-
return 0;
err:
- 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;
}
module_exit(lttng_events_exit);
-#include <generated/patches.i>
+#include <generated/patches.h>
#ifdef LTTNG_EXTRA_VERSION_GIT
MODULE_INFO(extra_version_git, LTTNG_EXTRA_VERSION_GIT);
#endif