[ltt-dev] [PATCH] ltt-channel: permanent eID

Lai Jiangshan laijs at cn.fujitsu.com
Tue Dec 16 08:28:53 EST 2008


introduce permanent eID for text output, and change
the ltt-channel's management.

Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
---
 include/linux/ltt-channels.h |   45 ++++++-
 include/linux/marker.h       |    4
 kernel/marker.c              |   95 +++------------
 ltt/ltt-channels.c           |  271 +++++++++++++++++++++++++------------------
 ltt/ltt-tracer.c             |    9 +
 5 files changed, 230 insertions(+), 194 deletions(-)
diff --git a/include/linux/ltt-channels.h b/include/linux/ltt-channels.h
index ce19eda..edf959b 100644
--- a/include/linux/ltt-channels.h
+++ b/include/linux/ltt-channels.h
@@ -8,8 +8,10 @@
  */
 
 #include <linux/limits.h>
+#include <linux/marker.h>
 
 #define EVENTS_PER_CHANNEL	65536
+#define EVENTS_MOST_WASTE_IDS	128
 
 struct ltt_trace_struct;
 struct rchan_buf;
@@ -51,15 +53,51 @@ struct ltt_channel_struct {
 struct ltt_channel_setting {
 	unsigned int subbuf_size;
 	unsigned int subbuf_cnt;
-	struct kref kref;	/* Number of references to structure content */
+	int trace_count;
+	int live_count;
 	struct list_head list;
+	struct list_head marker_entry;
 	unsigned int index;	/* index of channel in trace channel array */
 	u16 free_event_id;	/* Next event ID to allocate */
 	char name[PATH_MAX];
 };
 
-int ltt_channels_register(const char *name);
-int ltt_channels_unregister(const char *name);
+/*
+ * Note about RCU :
+ * It is used to make sure every handler has finished using its private data
+ * between two consecutive operation (add or remove) on a given marker.  It is
+ * also used to delay the free of multiple probes array until a quiescent state
+ * is reached.
+ * marker entries modifications are protected by the markers_mutex.
+ */
+struct marker_entry {
+	struct hlist_node hlist;
+	char *format;
+	char *name;
+			/* Probe wrapper */
+	void (*call)(const struct marker *mdata, void *call_private, ...);
+	struct marker_probe_closure single;
+	struct marker_probe_closure *multi;
+	int refcount;	/* Number of times armed. 0 if disarmed. */
+	struct rcu_head rcu;
+	void *oldptr;
+	int rcu_pending;
+	u16 channel_id;
+	u16 event_id;
+	unsigned char ptype:1;
+	unsigned char format_allocated:1;
+	unsigned char used:1;
+	struct list_head sibling;	/* sibling of channel's maker_entry */
+	struct ltt_channel_setting *lcs;
+	char channel[0];	/* Contains channel'\0'name'\0'format'\0' */
+};
+int __makrer_set_channel(struct marker_entry *entry, const char *channel);
+
+int start_trace_channel(const char *channel);
+int stop_trace_channel(const char *channel);
+const char *get_name_from_eid(const char *channel, u16 eID);
+const char *get_fmt_from_eid(const char *channel, u16 eID);
+
 int ltt_channels_set_default(const char *name,
 			     unsigned int subbuf_size,
 			     unsigned int subbuf_cnt);
@@ -69,7 +107,6 @@ struct ltt_channel_struct *ltt_channels_trace_alloc(unsigned int *nr_channels,
 						    int overwrite,
 						    int active);
 void ltt_channels_trace_free(struct ltt_channel_struct *channels);
-int _ltt_channels_get_event_id(const char *channel, const char *name);
 int ltt_channels_get_event_id(const char *channel, const char *name);
 
 #endif /* _LTT_CHANNELS_H */
diff --git a/include/linux/marker.h b/include/linux/marker.h
index 32387e8..82e4f7c 100644
--- a/include/linux/marker.h
+++ b/include/linux/marker.h
@@ -15,7 +15,6 @@
 #include <stdarg.h>
 #include <linux/types.h>
 #include <linux/immediate.h>
-#include <linux/ltt-channels.h>
 
 struct module;
 struct task_struct;
@@ -126,6 +125,7 @@ struct marker {
 
 extern void marker_update_probe_range(struct marker *begin,
 	struct marker *end);
+extern void marker_update_probes(void);
 
 #define GET_MARKER(channel, name)	(__mark_##channel##_##name)
 
@@ -199,8 +199,6 @@ static inline void marker_update_probe_range(struct marker *begin,
 extern void lock_markers(void);
 extern void unlock_markers(void);
 
-extern void markers_compact_event_ids(void);
-
 /* To be used for string format validity checking with gcc */
 static inline void __printf(1, 2) ___mark_check_format(const char *fmt, ...)
 {
diff --git a/kernel/marker.c b/kernel/marker.c
index b11a82a..cd38ba0 100644
--- a/kernel/marker.c
+++ b/kernel/marker.c
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/rcupdate.h>
 #include <linux/marker.h>
+#include <linux/ltt-channels.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/immediate.h>
@@ -60,33 +61,6 @@ void unlock_markers(void)
 #define MARKER_TABLE_SIZE (1 << MARKER_HASH_BITS)
 static struct hlist_head marker_table[MARKER_TABLE_SIZE];
 
-/*
- * Note about RCU :
- * It is used to make sure every handler has finished using its private data
- * between two consecutive operation (add or remove) on a given marker.  It is
- * also used to delay the free of multiple probes array until a quiescent state
- * is reached.
- * marker entries modifications are protected by the markers_mutex.
- */
-struct marker_entry {
-	struct hlist_node hlist;
-	char *format;
-	char *name;
-			/* Probe wrapper */
-	void (*call)(const struct marker *mdata, void *call_private, ...);
-	struct marker_probe_closure single;
-	struct marker_probe_closure *multi;
-	int refcount;	/* Number of times armed. 0 if disarmed. */
-	struct rcu_head rcu;
-	void *oldptr;
-	int rcu_pending;
-	u16 channel_id;
-	u16 event_id;
-	unsigned char ptype:1;
-	unsigned char format_allocated:1;
-	char channel[0];	/* Contains channel'\0'name'\0'format'\0' */
-};
-
 #ifdef CONFIG_MARKERS_USERSPACE
 static void marker_update_processes(void);
 #else
@@ -474,7 +448,6 @@ static int remove_marker(const char *channel, const char *name)
 	size_t channel_len = strlen(channel) + 1;
 	size_t name_len = strlen(name) + 1;
 	u32 hash;
-	int ret;
 
 	hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0);
 	head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
@@ -488,11 +461,26 @@ static int remove_marker(const char *channel, const char *name)
 		return -ENOENT;
 	if (e->single.func != __mark_empty_function)
 		return -EBUSY;
+
+	if (e->lcs) {
+		e->lcs->live_count--;
+		if (!e->lcs->live_count && !e->lcs->trace_count) {
+			BUG_ON(!list_empty(&e->lcs->marker_entry));
+			list_del(&e->lcs->list);
+			kfree(e->lcs);
+			e->lcs = NULL;
+		}
+	}
+
+	/* It will be released in remove_chanel_marker_entries() */
+	if (e->used && e->lcs && e->lcs->trace_count)
+		return 0;
+
 	hlist_del(&e->hlist);
 	if (e->format_allocated)
 		kfree(e->format);
-	ret = ltt_channels_unregister(e->channel);
-	WARN_ON(ret);
+	if (e->lcs)
+		list_del(&e->sibling);
 	/* Make sure the call_rcu has been executed */
 	if (e->rcu_pending)
 		rcu_barrier_sched();
@@ -540,6 +528,7 @@ static int set_marker(struct marker_entry *entry, struct marker *elem,
 		if (ret)
 			return ret;
 	}
+	entry->used = 1;
 
 	/*
 	 * probe_cb setup (statically known) is done here. It is
@@ -695,7 +684,7 @@ void marker_update_probe_range(struct marker *begin,
  * Site effect : marker_set_format may delete the marker entry (creating a
  * replacement).
  */
-static void marker_update_probes(void)
+void marker_update_probes(void)
 {
 	/* Core kernel markers */
 	marker_update_probe_range(__start___markers, __stop___markers);
@@ -738,18 +727,9 @@ int marker_probe_register(const char *channel, const char *name,
 			ret = PTR_ERR(entry);
 		if (ret)
 			goto end;
-		ret = ltt_channels_register(channel);
+		ret = __makrer_set_channel(entry, channel);
 		if (ret)
 			goto error_remove_marker;
-		ret = ltt_channels_get_index_from_name(channel);
-		if (ret < 0)
-			goto error_unregister_channel;
-		entry->channel_id = ret;
-		ret = ltt_channels_get_event_id(channel, name);
-		if (ret < 0)
-			goto error_unregister_channel;
-		entry->event_id = ret;
-		ret = 0;
 		trace_mark(metadata, core_marker_id,
 			   "channel %s name %s event_id %hu "
 			   "int #1u%zu long #1u%zu pointer #1u%zu "
@@ -776,7 +756,7 @@ int marker_probe_register(const char *channel, const char *name,
 	if (IS_ERR(old)) {
 		ret = PTR_ERR(old);
 		if (first_probe)
-			goto error_unregister_channel;
+			goto error_remove_marker;
 		else
 			goto end;
 	}
@@ -797,9 +777,6 @@ int marker_probe_register(const char *channel, const char *name,
 	call_rcu_sched(&entry->rcu, free_old_closure);
 	goto end;
 
-error_unregister_channel:
-	ret_err = ltt_channels_unregister(channel);
-	WARN_ON(ret_err);
 error_remove_marker:
 	ret_err = remove_marker(channel, name);
 	WARN_ON(ret_err);
@@ -997,34 +974,6 @@ void *marker_get_private_data(const char *channel, const char *name,
 }
 EXPORT_SYMBOL_GPL(marker_get_private_data);
 
-/**
- * markers_compact_event_ids: Compact markers event IDs and reassign channels
- *
- * Called when no channel users are active by the channel infrastructure.
- * Called with lock_markers() and channel mutex held.
- */
-void markers_compact_event_ids(void)
-{
-	struct marker_entry *entry;
-	unsigned int i;
-	struct hlist_head *head;
-	struct hlist_node *node;
-	int ret;
-
-	for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-		head = &marker_table[i];
-		hlist_for_each_entry(entry, node, head, hlist) {
-			ret = ltt_channels_get_index_from_name(entry->channel);
-			WARN_ON(ret < 0);
-			entry->channel_id = ret;
-			ret = _ltt_channels_get_event_id(entry->channel,
-							 entry->name);
-			WARN_ON(ret < 0);
-			entry->event_id = ret;
-		}
-	}
-}
-
 #ifdef CONFIG_MODULES
 
 /**
diff --git a/ltt/ltt-channels.c b/ltt/ltt-channels.c
index c57e737..e876f04 100644
--- a/ltt/ltt-channels.c
+++ b/ltt/ltt-channels.c
@@ -13,13 +13,12 @@
 #include <linux/ltt-channels.h>
 #include <linux/mutex.h>
 #include <linux/vmalloc.h>
+#include <linux/marker.h>
+#include <linux/err.h>
+#include <linux/ltt-tracer.h>
+
+LIST_HEAD(ltt_channels);
 
-/*
- * ltt_channel_mutex may be nested inside the LTT trace mutex.
- * ltt_channel_mutex mutex may be nested inside markers mutex.
- */
-static DEFINE_MUTEX(ltt_channel_mutex);
-static LIST_HEAD(ltt_channels);
 /*
  * Index of next channel in array. Makes sure that as long as a trace channel is
  * allocated, no array index will be re-used when a channel is freed and then
@@ -40,104 +39,165 @@ static struct ltt_channel_setting *lookup_channel(const char *name)
 	return NULL;
 }
 
-/*
- * Must be called when channel refcount falls to 0 _and_ also when the last
- * trace is freed. This function is responsible for compacting the channel and
- * event IDs when no users are active.
- *
- * Called with lock_markers() and channels mutex held.
- */
-static void release_channel_setting(struct kref *kref)
-{
-	struct ltt_channel_setting *setting = container_of(kref,
-		struct ltt_channel_setting, kref);
-	struct ltt_channel_setting *iter;
+static int _ltt_channels_get_event_id(struct ltt_channel_setting *setting,
+		const char *name);
 
-	if (atomic_read(&index_kref.refcount) == 0
-	    && atomic_read(&setting->kref.refcount) == 0) {
-		list_del(&setting->list);
-		kfree(setting);
+int __makrer_set_channel(struct marker_entry *entry, const char *channel)
+{
+	struct ltt_channel_setting *setting = lookup_channel(channel);
+	if (!setting) {
+		setting = kzalloc(sizeof(*setting), GFP_KERNEL);
+		if (!setting)
+			return -ENOMEM;
+		list_add_tail(&setting->list, &ltt_channels);
+		strncpy(setting->name, channel, PATH_MAX-1);
+		setting->index = free_index++;
+		INIT_LIST_HEAD(&setting->marker_entry);
+	}else if (setting->free_event_id == EVENTS_PER_CHANNEL - 1)
+		return -ENOSPC;
+	setting->live_count++;
+	list_add(&entry->sibling, &setting->marker_entry);
+	entry->channel_id = setting->index;
+	entry->event_id = _ltt_channels_get_event_id(setting, entry->name);
+	return 0;
+}
 
-		free_index = 0;
-		list_for_each_entry(iter, &ltt_channels, list) {
-			iter->index = free_index++;
-			iter->free_event_id = 0;
+static void defrag_id(struct ltt_channel_setting *setting)
+{
+	struct marker_entry *e;
+	int free_count = setting->free_event_id;
+	if (setting->live_count + EVENTS_MOST_WASTE_IDS > free_count)
+		return;
+	free_count = 0;
+	list_for_each_entry(e, &setting->marker_entry, sibling) {
+		if (e->event_id != free_count) {
+			trace_mark(metadata, core_marker_id,
+				   "channel %s name %s event_id %hu "
+				   "int #1u%zu long #1u%zu pointer #1u%zu "
+				   "size_t #1u%zu alignment #1u%u",
+				   e->channel, e->name, (u16)free_count,
+				   sizeof(int), sizeof(long), sizeof(void *),
+				   sizeof(size_t), ltt_get_alignment());
 		}
-		markers_compact_event_ids();
+		e->event_id = free_count++;
 	}
+	setting->free_event_id = (u16)free_count;
+	marker_update_probes();
 }
 
-/*
- * Perform channel index compaction when the last trace channel is freed.
- *
- * Called with lock_markers() and channels mutex held.
- */
-static void release_trace_channel(struct kref *kref)
+static void remove_chanel_marker_entries(struct ltt_channel_setting *setting)
 {
-	struct ltt_channel_setting *iter, *n;
+	struct marker_entry *e, *n;
+
+	list_for_each_entry_safe(e, n, &setting->marker_entry, sibling) {
+		if (e->single.func != __mark_empty_function)
+			continue;
 
-	list_for_each_entry_safe(iter, n, &ltt_channels, list)
-		release_channel_setting(&iter->kref);
+		hlist_del(&e->hlist);
+		if (e->format_allocated)
+			kfree(e->format);
+		list_del(&e->sibling);
+		/* Make sure the call_rcu has been executed */
+		if (e->rcu_pending)
+			rcu_barrier_sched();
+		kfree(e);
+	}
 }
 
-/**
- * ltt_channels_register: Register a trace channel.
- *
- * Uses refcounting.
- */
-int ltt_channels_register(const char *name)
+int start_trace_channel(const char *channel)
 {
+	int ret = -ENOENT;
 	struct ltt_channel_setting *setting;
-	int ret = 0;
 
-	mutex_lock(&ltt_channel_mutex);
-	setting = lookup_channel(name);
+	lock_markers();
+	setting = lookup_channel(channel);
+	if (setting) {
+		if (!setting->trace_count)
+			defrag_id(setting);
+		setting->trace_count++;
+		ret = 0;
+	}
+	unlock_markers();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(start_trace_channel);
+
+int stop_trace_channel(const char *channel)
+{
+	int ret = -ENOENT;
+	struct ltt_channel_setting *setting;
+
+	lock_markers();
+	setting = lookup_channel(channel);
 	if (setting) {
-		if (atomic_read(&setting->kref.refcount) == 0)
-			goto init_kref;
-		else {
-			kref_get(&setting->kref);
-			goto end;
+		setting->trace_count--;
+		if (!setting->trace_count)
+			remove_chanel_marker_entries(setting);
+		ret = 0;
+		if (!setting->live_count && !setting->trace_count) {
+			BUG_ON(!list_empty(&setting->marker_entry));
+			list_del(&setting->list);
+			kfree(setting);
 		}
 	}
-	setting = kzalloc(sizeof(*setting), GFP_KERNEL);
-	if (!setting) {
-		ret = -ENOMEM;
-		goto end;
+	unlock_markers();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(stop_trace_channel);
+
+/* permanent! the return value is valid before stop_strace_channel() */
+
+const char *get_name_from_eid(const char *channel, u16 eID)
+{
+	char *ret = ERR_PTR(-ENOENT);
+	struct ltt_channel_setting *setting;
+	struct marker_entry *e;
+
+	lock_markers();
+	setting = lookup_channel(channel);
+	list_for_each_entry(e, &setting->marker_entry, sibling) {
+		if (e->event_id == eID) {
+			ret = e->name;
+			break;
+		}
 	}
-	list_add(&setting->list, &ltt_channels);
-	strncpy(setting->name, name, PATH_MAX-1);
-	setting->index = free_index++;
-init_kref:
-	kref_init(&setting->kref);
-end:
-	mutex_unlock(&ltt_channel_mutex);
+	unlock_markers();
 	return ret;
 }
-EXPORT_SYMBOL_GPL(ltt_channels_register);
+EXPORT_SYMBOL_GPL(get_name_from_eid);
 
-/**
- * ltt_channels_unregister(): Unregister a trace channel.
- *
- * Must be called with markers mutex held.
- */
-int ltt_channels_unregister(const char *name)
+const char *get_fmt_from_eid(const char *channel, u16 eID)
 {
+	char *ret = ERR_PTR(-ENOENT);
 	struct ltt_channel_setting *setting;
-	int ret = 0;
+	struct marker_entry *e;
 
-	mutex_lock(&ltt_channel_mutex);
-	setting = lookup_channel(name);
-	if (!setting || atomic_read(&setting->kref.refcount) == 0) {
-		ret = -ENOENT;
-		goto end;
+	lock_markers();
+	setting = lookup_channel(channel);
+	list_for_each_entry(e, &setting->marker_entry, sibling) {
+		if (e->event_id == eID) {
+			if (e->used)
+				ret = e->format;
+			break;
+		}
 	}
-	kref_put(&setting->kref, release_channel_setting);
-end:
-	mutex_unlock(&ltt_channel_mutex);
+	unlock_markers();
 	return ret;
 }
-EXPORT_SYMBOL_GPL(ltt_channels_unregister);
+EXPORT_SYMBOL_GPL(get_fmt_from_eid);
+
+/*
+ * Must be called when channel refcount falls to 0 _and_ also when the last
+ * trace is freed. This function is responsible for compacting the channel
+ * index when no users are active.
+ */
+static void release_channel_index(struct kref *kref)
+{
+	struct ltt_channel_setting *setting;
+	free_index = 0;
+	list_for_each_entry(setting, &ltt_channels, list)
+		setting->index = free_index++;
+}
 
 /**
  * ltt_channels_set_default: Set channel default behavior.
@@ -149,16 +209,16 @@ int ltt_channels_set_default(const char *name,
 	struct ltt_channel_setting *setting;
 	int ret = 0;
 
-	mutex_lock(&ltt_channel_mutex);
+	lock_markers();
 	setting = lookup_channel(name);
-	if (!setting || atomic_read(&setting->kref.refcount) == 0) {
+	if (!setting) {
 		ret = -ENOENT;
 		goto end;
 	}
 	setting->subbuf_size = subbuf_size;
 	setting->subbuf_cnt = subbuf_cnt;
 end:
-	mutex_unlock(&ltt_channel_mutex);
+	unlock_markers();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(ltt_channels_set_default);
@@ -174,7 +234,7 @@ const char *ltt_channels_get_name_from_index(unsigned int index)
 	struct ltt_channel_setting *iter;
 
 	list_for_each_entry(iter, &ltt_channels, list)
-		if (iter->index == index && atomic_read(&iter->kref.refcount))
+		if (iter->index == index)
 			return iter->name;
 	return NULL;
 }
@@ -186,8 +246,7 @@ ltt_channels_get_setting_from_name(const char *name)
 	struct ltt_channel_setting *iter;
 
 	list_for_each_entry(iter, &ltt_channels, list)
-		if (!strcmp(iter->name, name)
-		    && atomic_read(&iter->kref.refcount))
+		if (!strcmp(iter->name, name))
 			return iter;
 	return NULL;
 }
@@ -228,7 +287,7 @@ struct ltt_channel_struct *ltt_channels_trace_alloc(unsigned int *nr_channels,
 	struct ltt_channel_struct *channel = NULL;
 	struct ltt_channel_setting *iter;
 
-	mutex_lock(&ltt_channel_mutex);
+	lock_markers();
 	if (!free_index)
 		goto end;
 	if (!atomic_read(&index_kref.refcount))
@@ -241,7 +300,7 @@ struct ltt_channel_struct *ltt_channels_trace_alloc(unsigned int *nr_channels,
 	if (!channel)
 		goto end;
 	list_for_each_entry(iter, &ltt_channels, list) {
-		if (!atomic_read(&iter->kref.refcount))
+		if (!iter->live_count)
 			continue;
 		channel[iter->index].subbuf_size = iter->subbuf_size;
 		channel[iter->index].subbuf_cnt = iter->subbuf_cnt;
@@ -250,7 +309,7 @@ struct ltt_channel_struct *ltt_channels_trace_alloc(unsigned int *nr_channels,
 		channel[iter->index].channel_name = iter->name;
 	}
 end:
-	mutex_unlock(&ltt_channel_mutex);
+	unlock_markers();
 	return channel;
 }
 EXPORT_SYMBOL_GPL(ltt_channels_trace_alloc);
@@ -264,33 +323,18 @@ EXPORT_SYMBOL_GPL(ltt_channels_trace_alloc);
 void ltt_channels_trace_free(struct ltt_channel_struct *channels)
 {
 	lock_markers();
-	mutex_lock(&ltt_channel_mutex);
-	kfree(channels);
-	kref_put(&index_kref, release_trace_channel);
-	mutex_unlock(&ltt_channel_mutex);
+	kref_put(&index_kref, release_channel_index);
 	unlock_markers();
+	kfree(channels);
 }
 EXPORT_SYMBOL_GPL(ltt_channels_trace_free);
 
-/**
- * _ltt_channels_get_event_id: get next event ID for a marker
- * @channel: channel name
- * @name: event name
- *
- * Returns a unique event ID (for this channel) or < 0 on error.
- * Must be called with channels mutex held.
- */
-int _ltt_channels_get_event_id(const char *channel, const char *name)
+static int _ltt_channels_get_event_id(struct ltt_channel_setting *setting,
+		const char *name)
 {
-	struct ltt_channel_setting *setting;
 	int ret;
 
-	setting = ltt_channels_get_setting_from_name(channel);
-	if (!setting) {
-		ret = -ENOENT;
-		goto end;
-	}
-	if (strcmp(channel, "metadata") == 0) {
+	if (strcmp(setting->name, "metadata") == 0) {
 		if (strcmp(name, "core_marker_id") == 0)
 			ret = 0;
 		else if (strcmp(name, "core_marker_format") == 0)
@@ -299,7 +343,7 @@ int _ltt_channels_get_event_id(const char *channel, const char *name)
 			ret = -ENOENT;
 		goto end;
 	}
-	if (setting->free_event_id == EVENTS_PER_CHANNEL) {
+	if (setting->free_event_id == EVENTS_PER_CHANNEL - 1) {
 		ret = -ENOSPC;
 		goto end;
 	}
@@ -316,11 +360,14 @@ end:
  */
 int ltt_channels_get_event_id(const char *channel, const char *name)
 {
-	int ret;
+	int ret = -ENOENT;
+	struct ltt_channel_setting *setting;
 
-	mutex_lock(&ltt_channel_mutex);
-	ret = _ltt_channels_get_event_id(channel, name);
-	mutex_unlock(&ltt_channel_mutex);
+	lock_markers();
+	setting = ltt_channels_get_setting_from_name(channel);
+	if (setting)
+		ret = _ltt_channels_get_event_id(setting, name);
+	unlock_markers();
 	return ret;
 }
 
diff --git a/ltt/ltt-tracer.c b/ltt/ltt-tracer.c
index af14135..71289f9 100644
--- a/ltt/ltt-tracer.c
+++ b/ltt/ltt-tracer.c
@@ -772,6 +772,7 @@ int ltt_trace_alloc(const char *trace_name)
 		subbuf_size = trace->channels[chan].subbuf_size;
 		subbuf_cnt = trace->channels[chan].subbuf_cnt;
 		prepare_chan_size_num(&subbuf_size, &subbuf_cnt);
+		start_trace_channel(channel_name);
 		err = trace->ops->create_channel(trace_name, trace,
 				trace->dentry.trace_root,
 				channel_name,
@@ -801,8 +802,10 @@ int ltt_trace_alloc(const char *trace_name)
 
 create_channel_error:
 	for (chan--; chan >= 0; chan--)
-		if (trace->channels[chan].active)
+		if (trace->channels[chan].active) {
 			trace->ops->remove_channel(&trace->channels[chan]);
+			stop_trace_channel(trace->channels[chan].channel_name);
+		}
 
 dirs_error:
 	module_put(trace->transport->owner);
@@ -901,8 +904,10 @@ static void __ltt_trace_destroy(struct ltt_trace_struct	*trace)
 
 	for (i = 0; i < trace->nr_channels; i++) {
 		chan = &trace->channels[i];
-		if (chan->active)
+		if (chan->active) {
 			trace->ops->remove_channel(chan);
+			stop_trace_channel(chan->channel_name);
+		}
 	}
 
 	kref_put(&trace->ltt_transport_kref, ltt_release_transport);






More information about the lttng-dev mailing list