[RFC patch 35/41] Marker API update

Mathieu Desnoyers
2009-03-05T23:30:37Z

[-- Attachment #1: marker.c-api-update.patch --]
[-- Type: text/plain, Size: 9930 bytes --]

Add channel id field to marker structure. Identifies the buffer group in which
the event will be written. Adapt the marker.c file to manage the new field.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
kernel/marker.c | 115 ++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 84 insertions(+), 31 deletions(-)

Index: linux-2.6-lttng/kernel/marker.c
===================================================================
--- linux-2.6-lttng.orig/kernel/marker.c 2009-02-06 15:52:18.000000000 -0500
+++ linux-2.6-lttng/kernel/marker.c 2009-02-06 15:52:36.000000000 -0500
@@ -25,6 +25,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/immediate.h>
+#include <linux/ltt-tracer.h>

extern struct marker __start___markers[];
extern struct marker __stop___markers[];
@@ -76,7 +77,7 @@ struct marker_entry {
struct rcu_head rcu;
void *oldptr;
int rcu_pending;
- u16 chan_id;
+ u16 channel_id;
u16 event_id;
unsigned char ptype:1;
unsigned char format_allocated:1;
@@ -85,6 +86,7 @@ struct marker_entry {

/**
* __mark_empty_function - Empty probe callback
+ * @mdata: marker data
* @probe_private: probe private data
* @call_private: call site private data
* @fmt: format string
@@ -95,8 +97,8 @@ struct marker_entry {
* though the function pointer change and the marker enabling are two distinct
* operations that modifies the execution flow of preemptible code.
*/
-notrace void __mark_empty_function(void *probe_private, void *call_private,
- const char *fmt, va_list *args)
+notrace void __mark_empty_function(const struct marker *mdata,
+ void *probe_private, void *call_private, const char *fmt, va_list *args)
{
}
EXPORT_SYMBOL_GPL(__mark_empty_function);
@@ -134,8 +136,8 @@ notrace void marker_probe_cb(const struc
* dependant, so we put an explicit smp_rmb() here. */
smp_rmb();
va_start(args, call_private);
- func(mdata->single.probe_private, call_private, mdata->format,
- &args);
+ func(mdata, mdata->single.probe_private, call_private,
+ mdata->format, &args);
va_end(args);
} else {
struct marker_probe_closure *multi;
@@ -155,8 +157,8 @@ notrace void marker_probe_cb(const struc
smp_read_barrier_depends();
for (i = 0; multi[i].func; i++) {
va_start(args, call_private);
- multi[i].func(multi[i].probe_private, call_private,
- mdata->format, &args);
+ multi[i].func(mdata, multi[i].probe_private,
+ call_private, mdata->format, &args);
va_end(args);
}
}
@@ -189,8 +191,8 @@ static notrace void marker_probe_cb_noar
/* Must read the ptr before private data. They are not data
* dependant, so we put an explicit smp_rmb() here. */
smp_rmb();
- func(mdata->single.probe_private, call_private, mdata->format,
- &args);
+ func(mdata, mdata->single.probe_private, call_private,
+ mdata->format, &args);
} else {
struct marker_probe_closure *multi;
int i;
@@ -208,8 +210,8 @@ static notrace void marker_probe_cb_noar
*/
smp_read_barrier_depends();
for (i = 0; multi[i].func; i++)
- multi[i].func(multi[i].probe_private, call_private,
- mdata->format, &args);
+ multi[i].func(mdata, multi[i].probe_private,
+ call_private, mdata->format, &args);
}
rcu_read_unlock_sched_notrace();
}
@@ -218,13 +220,6 @@ static void free_old_closure(struct rcu_
{
struct marker_entry *entry = container_of(head,
struct marker_entry, rcu);
- int ret;
-
- /* Single probe removed */
- if (!entry->ptype) {
- ret = ltt_channels_unregister(entry->channel);
- WARN_ON(ret);
- }
kfree(entry->oldptr);
/* Make sure we free the data before setting the pending flag to 0 */
smp_wmb();
@@ -437,8 +432,9 @@ static struct marker_entry *add_marker(c
e->call = marker_probe_cb_noarg;
else
e->call = marker_probe_cb;
- trace_mark(core_marker_format, "name %s format %s",
- e->name, e->format);
+ trace_mark(metadata, core_marker_format,
+ "channel %s name %s format %s",
+ e->channel, e->name, e->format);
} else {
e->format = NULL;
e->call = marker_probe_cb;
@@ -458,7 +454,7 @@ static struct marker_entry *add_marker(c
* Remove the marker from the marker hash table. Must be called with mutex_lock
* held.
*/
-static int remove_marker(const char *name)
+static int remove_marker(const char *channel, const char *name)
{
struct hlist_head *head;
struct hlist_node *node;
@@ -467,6 +463,7 @@ static int remove_marker(const char *nam
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)];
@@ -483,6 +480,8 @@ static int remove_marker(const char *nam
hlist_del(&e->hlist);
if (e->format_allocated)
kfree(e->format);
+ ret = ltt_channels_unregister(e->channel);
+ WARN_ON(ret);
/* Make sure the call_rcu has been executed */
if (e->rcu_pending)
rcu_barrier_sched();
@@ -500,8 +499,9 @@ static int marker_set_format(struct mark
return -ENOMEM;
entry->format_allocated = 1;

- trace_mark(core_marker_format, "name %s format %s",
- entry->name, entry->format);
+ trace_mark(metadata, core_marker_format,
+ "channel %s name %s format %s",
+ entry->channel, entry->name, entry->format);
return 0;
}

@@ -537,6 +537,8 @@ static int set_marker(struct marker_entr
* callback (does not set arguments).
*/
elem->call = entry->call;
+ elem->channel_id = entry->channel_id;
+ elem->event_id = entry->event_id;
/*
* Sanity check :
* We only update the single probe private data when the ptr is
@@ -631,9 +633,9 @@ static void disable_marker(struct marker
smp_wmb();
elem->ptype = 0; /* single probe */
/*
- * Leave the private data and id there, because removal is racy and
- * should be done only after an RCU period. These are never used until
- * the next initialization anyway.
+ * Leave the private data and channel_id/event_id there, because removal
+ * is racy and should be done only after an RCU period. These are never
+ * used until the next initialization anyway.
*/
}

@@ -652,7 +654,7 @@ void marker_update_probe_range(struct ma

mutex_lock(&markers_mutex);
for (iter = begin; iter < end; iter++) {
- mark_entry = get_marker(iter->name);
+ mark_entry = get_marker(iter->channel, iter->name);
if (mark_entry) {
set_marker(mark_entry, iter, !!mark_entry->refcount);
/*
@@ -716,7 +718,7 @@ int marker_probe_register(const char *ch
int first_probe = 0;

mutex_lock(&markers_mutex);
- entry = get_marker(name);
+ entry = get_marker(channel, name);
if (!entry) {
first_probe = 1;
entry = add_marker(channel, name, format);
@@ -731,10 +733,18 @@ int marker_probe_register(const char *ch
if (ret < 0)
goto error_unregister_channel;
entry->channel_id = ret;
- ret = ltt_channels_get_event_id(channel);
+ 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 "
+ "size_t #1u%zu alignment #1u%u",
+ channel, name, entry->event_id,
+ sizeof(int), sizeof(long), sizeof(void *),
+ sizeof(size_t), ltt_get_alignment());
} else if (format) {
if (!entry->format)
ret = marker_set_format(entry, format);
@@ -773,6 +783,7 @@ int marker_probe_register(const char *ch
/* write rcu_pending before calling the RCU callback */
smp_wmb();
call_rcu_sched(&entry->rcu, free_old_closure);
+ goto end;

error_unregister_channel:
ret_err = ltt_channels_unregister(channel);
@@ -978,7 +989,7 @@ EXPORT_SYMBOL_GPL(marker_get_private_dat
* 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() held.
+ * Called with lock_markers() and channel mutex held.
*/
void markers_compact_event_ids(void)
{
@@ -986,6 +997,7 @@ void markers_compact_event_ids(void)
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];
@@ -993,7 +1005,8 @@ void markers_compact_event_ids(void)
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);
+ ret = _ltt_channels_get_event_id(entry->channel,
+ entry->name);
WARN_ON(ret < 0);
entry->event_id = ret;
}
@@ -1102,3 +1115,43 @@ static int init_markers(void)
__initcall(init_markers);

#endif /* CONFIG_MODULES */
+
+void ltt_dump_marker_state(struct ltt_trace_struct *trace)
+{
+ struct marker_iter iter;
+ struct ltt_probe_private_data call_data;
+ const char *channel;
+
+ call_data.trace = trace;
+ call_data.serializer = NULL;
+
+ marker_iter_reset(&iter);
+ marker_iter_start(&iter);
+ for (; iter.marker != NULL; marker_iter_next(&iter)) {
+ if (!_imv_read(iter.marker->state))
+ continue;
+ channel = ltt_channels_get_name_from_index(
+ iter.marker->channel_id);
+ __trace_mark(0, metadata, core_marker_id,
+ &call_data,
+ "channel %s name %s event_id %hu "
+ "int #1u%zu long #1u%zu pointer #1u%zu "
+ "size_t #1u%zu alignment #1u%u",
+ channel,
+ iter.marker->name,
+ iter.marker->event_id,
+ sizeof(int), sizeof(long),
+ sizeof(void *), sizeof(size_t),
+ ltt_get_alignment());
+ if (iter.marker->format)
+ __trace_mark(0, metadata,
+ core_marker_format,
+ &call_data,
+ "channel %s name %s format %s",
+ channel,
+ iter.marker->name,
+ iter.marker->format);
+ }
+ marker_iter_stop(&iter);
+}
+EXPORT_SYMBOL_GPL(ltt_dump_marker_state);