The marker activation functions sits in kernel/marker.c. A hash table is used
to keep track of the registered probes and armed markers, so the markers within
a newly loaded module that should be active can be activated at module load
time.
marker_query has been removed. marker_get_first, marker_get_next and
marker_release should be used as iterators on the markers.
Changelog:
- markers_mutex now nests inside module_mutex rather than the opposite.
- Iteration on modules is now done in module.c.
- module_mutex is not exported anymore.
- Don't declare a __markers_strings section.
- Simplified: do not use immediate values, just a simple variable read.
(removed dependency on immediate values).
- Removed the args field in the marker structure : it was not used.
- Removed the iterators. Will come back with the actual users.
- Merge the markers menu entry.
Signed-off-by: Mathieu Desnoyers <[email protected]>
Acked-by: "Frank Ch. Eigler" <[email protected]>
CC: Christoph Hellwig <[email protected]>
CC: Rusty Russell <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 7
include/linux/marker.h | 130 +++++++++
include/linux/module.h | 12
kernel/Kconfig.instrumentation | 6
kernel/Makefile | 1
kernel/marker.c | 527 ++++++++++++++++++++++++++++++++++++++
kernel/module.c | 30 ++
7 files changed, 711 insertions(+), 2 deletions(-)
Index: linux-2.6-lttng/include/asm-generic/vmlinux.lds.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-generic/vmlinux.lds.h 2007-09-25 07:17:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-generic/vmlinux.lds.h 2007-09-25 07:18:50.000000000 -0400
@@ -12,7 +12,11 @@
/* .data section */
#define DATA_DATA \
*(.data) \
- *(.data.init.refok)
+ *(.data.init.refok) \
+ . = ALIGN(8); \
+ VMLINUX_SYMBOL(__start___markers) = .; \
+ *(__markers) \
+ VMLINUX_SYMBOL(__stop___markers) = .;
#define RO_DATA(align) \
. = ALIGN((align)); \
@@ -20,6 +24,7 @@
VMLINUX_SYMBOL(__start_rodata) = .; \
*(.rodata) *(.rodata.*) \
*(__vermagic) /* Kernel version magic */ \
+ *(__markers_strings) /* Markers: strings */ \
} \
\
.rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
Index: linux-2.6-lttng/include/linux/marker.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/include/linux/marker.h 2007-09-25 07:18:50.000000000 -0400
@@ -0,0 +1,130 @@
+#ifndef _LINUX_MARKER_H
+#define _LINUX_MARKER_H
+
+/*
+ * Code markup for dynamic and static tracing.
+ *
+ * See Documentation/marker.txt.
+ *
+ * (C) Copyright 2006 Mathieu Desnoyers <[email protected]>
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+
+struct module;
+struct __mark_marker;
+
+/**
+ * marker_probe_func - Type of a marker probe function
+ * @mdata: pointer of type struct __mark_marker
+ * @private_data: caller site private data
+ * @fmt: format string
+ * @...: variable argument list
+ *
+ * Type of marker probe functions. They receive the mdata and need to parse the
+ * format string to recover the variable argument list.
+ */
+typedef void marker_probe_func(const struct __mark_marker *mdata,
+ void *private_data, const char *fmt, ...);
+
+struct __mark_marker {
+ const char *name; /* Marker name */
+ const char *format; /* Marker format string, describing the
+ * variable argument list.
+ */
+ char state; /* Marker state. */
+ marker_probe_func *call;/* Probe handler function pointer */
+ void *private; /* Private probe data */
+} __attribute__((aligned(8)));
+
+#ifdef CONFIG_MARKERS
+
+/*
+ * Note : the empty asm volatile with read constraint is used here instead of a
+ * "used" attribute to fix a gcc 4.1.x bug.
+ * Make sure the alignment of the structure in the __markers section will
+ * not add unwanted padding between the beginning of the section and the
+ * structure. Force alignment to the same alignment as the section start.
+ */
+#define __trace_mark(name, call_data, format, args...) \
+ do { \
+ static const char __mstrtab_name_##name[] \
+ __attribute__((section("__markers_strings"))) \
+ = #name; \
+ static const char __mstrtab_format_##name[] \
+ __attribute__((section("__markers_strings"))) \
+ = format; \
+ static struct __mark_marker __mark_##name \
+ __attribute__((section("__markers"))) = \
+ { __mstrtab_name_##name, __mstrtab_format_##name, \
+ 0, __mark_empty_function, NULL }; \
+ asm volatile ( "" : : "i" (&__mark_##name)); \
+ __mark_check_format(format, ## args); \
+ if (unlikely(__mark_##name.state)) { \
+ preempt_disable(); \
+ (*__mark_##name.call) \
+ (&__mark_##name, call_data, \
+ format, ## args); \
+ preempt_enable(); \
+ } \
+ } while (0)
+
+extern void marker_update_probe_range(struct __mark_marker *begin,
+ struct __mark_marker *end, struct module *probe_module, int *refcount);
+#else /* !CONFIG_MARKERS */
+#define __trace_mark(name, call_data, format, args...) \
+ __mark_check_format(format, ## args)
+static inline void marker_update_probe_range(struct __mark_marker *begin,
+ struct __mark_marker *end, struct module *probe_module, int *refcount)
+{ }
+#endif /* CONFIG_MARKERS */
+
+/**
+ * trace_mark - Marker
+ * @name: marker name, not quoted.
+ * @format: format string
+ * @args...: variable argument list
+ *
+ * Places a marker.
+ */
+#define trace_mark(name, format, args...) \
+ __trace_mark(name, NULL, format, ## args)
+
+#define MARK_MAX_FORMAT_LEN 1024
+
+/**
+ * MARK_NOARGS - Format string for a marker with no argument.
+ */
+#define MARK_NOARGS " "
+
+/* To be used for string format validity checking with gcc */
+static inline void __printf(1, 2) __mark_check_format(const char *fmt, ...)
+{
+}
+
+extern marker_probe_func __mark_empty_function;
+
+/*
+ * Connect a probe to a marker.
+ * private data pointer must be a valid allocated memory address, or NULL.
+ */
+extern int marker_probe_register(const char *name, const char *format,
+ marker_probe_func *probe, void *private);
+
+/*
+ * Returns the private data given to marker_probe_register.
+ */
+extern void *marker_probe_unregister(const char *name);
+/*
+ * Unregister a marker by providing the registered private data.
+ */
+extern void *marker_probe_unregister_private_data(void *private);
+
+extern int marker_arm(const char *name);
+extern int marker_disarm(const char *name);
+extern void *marker_get_private_data(const char *name);
+
+#endif
Index: linux-2.6-lttng/include/linux/module.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/module.h 2007-09-25 07:17:49.000000000 -0400
+++ linux-2.6-lttng/include/linux/module.h 2007-09-25 07:18:50.000000000 -0400
@@ -15,6 +15,7 @@
#include <linux/stringify.h>
#include <linux/kobject.h>
#include <linux/moduleparam.h>
+#include <linux/marker.h>
#include <asm/local.h>
#include <asm/module.h>
@@ -370,6 +371,10 @@ struct module
/* The command line arguments (may be mangled). People like
keeping pointers to this stuff */
char *args;
+#ifdef CONFIG_MARKERS
+ struct __mark_marker *markers;
+ unsigned int num_markers;
+#endif
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
@@ -473,6 +478,8 @@ int unregister_module_notifier(struct no
extern void print_modules(void);
+extern void module_update_markers(struct module *probe_module, int *refcount);
+
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -572,6 +579,11 @@ static inline void print_modules(void)
{
}
+static inline void module_update_markers(struct module *probe_module,
+ int *refcount)
+{
+}
+
#endif /* CONFIG_MODULES */
struct device_driver;
Index: linux-2.6-lttng/kernel/module.c
===================================================================
--- linux-2.6-lttng.orig/kernel/module.c 2007-09-25 07:17:49.000000000 -0400
+++ linux-2.6-lttng/kernel/module.c 2007-09-25 07:18:50.000000000 -0400
@@ -1717,6 +1717,8 @@ static struct module *load_module(void _
unsigned int unusedcrcindex;
unsigned int unusedgplindex;
unsigned int unusedgplcrcindex;
+ unsigned int markersindex;
+ unsigned int markersstringsindex;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1982,6 +1984,8 @@ static struct module *load_module(void _
add_taint_module(mod, TAINT_FORCED_MODULE);
}
#endif
+ markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
+ markersstringsindex = find_sec(hdr, sechdrs, secstrings, "__markers_strings");
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -2004,6 +2008,11 @@ static struct module *load_module(void _
if (err < 0)
goto cleanup;
}
+#ifdef CONFIG_MARKERS
+ mod->markers = (void *)sechdrs[markersindex].sh_addr;
+ mod->num_markers =
+ sechdrs[markersindex].sh_size / sizeof(*mod->markers);
+#endif
/* Find duplicate symbols */
err = verify_export_symbols(mod);
@@ -2027,7 +2036,11 @@ static struct module *load_module(void _
if (err < 0)
goto nomodsectinfo;
#endif
-
+#ifdef CONFIG_MARKERS
+ if (!mod->taints)
+ marker_update_probe_range(mod->markers,
+ mod->markers + mod->num_markers, NULL, NULL);
+#endif
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
@@ -2629,3 +2642,18 @@ EXPORT_SYMBOL(module_remove_driver);
void struct_module(struct module *mod) { return; }
EXPORT_SYMBOL(struct_module);
#endif
+
+#ifdef CONFIG_MARKERS
+void module_update_markers(struct module *probe_module, int *refcount)
+{
+ struct module *mod;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(mod, &modules, list)
+ if (!mod->taints)
+ marker_update_probe_range(mod->markers,
+ mod->markers + mod->num_markers,
+ probe_module, refcount);
+ mutex_unlock(&module_mutex);
+}
+#endif
Index: linux-2.6-lttng/kernel/marker.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/kernel/marker.c 2007-09-25 07:18:50.000000000 -0400
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2007 Mathieu Desnoyers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+#include <linux/marker.h>
+#include <linux/err.h>
+
+extern struct __mark_marker __start___markers[];
+extern struct __mark_marker __stop___markers[];
+
+/*
+ * module_mutex nests inside markers_mutex. Markers mutex protects the builtin
+ * and module markers, the hash table and deferred_sync.
+ */
+DEFINE_MUTEX(markers_mutex);
+
+/*
+ * Marker deferred synchronization.
+ * Upon marker probe_unregister, we delay call to synchronize_sched() to
+ * accelerate mass unregistration (only when there is no more reference to a
+ * given module do we call synchronize_sched()). However, we need to make sure
+ * every critical region has ended before we re-arm a marker that has been
+ * unregistered and then registered back with a different probe data.
+ */
+static int deferred_sync;
+
+/*
+ * Marker hash table, containing the active markers.
+ * Protected by module_mutex.
+ */
+#define MARKER_HASH_BITS 6
+#define MARKER_TABLE_SIZE (1 << MARKER_HASH_BITS)
+
+struct marker_entry {
+ struct hlist_node hlist;
+ char *format;
+ marker_probe_func *probe;
+ void *private;
+ int refcount; /* Number of times armed. 0 if disarmed. */
+ char name[0]; /* Contains name'\0'format'\0' */
+};
+
+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
+
+/**
+ * __mark_empty_function - Empty probe callback
+ * @mdata: pointer of type const struct __mark_marker
+ * @fmt: format string
+ * @...: variable argument list
+ *
+ * Empty callback provided as a probe to the markers. By providing this to a
+ * disabled marker, we make sure the execution flow is always valid even
+ * though the function pointer change and the marker enabling are two distinct
+ * operations that modifies the execution flow of preemptible code.
+ */
+void __mark_empty_function(const struct __mark_marker *mdata,
+ void *private_data,
+ const char *fmt, ...)
+{
+}
+EXPORT_SYMBOL_GPL(__mark_empty_function);
+
+/*
+ * Get marker if the marker is present in the marker hash table.
+ * Must be called with markers_mutex held.
+ * Returns NULL if not present.
+ */
+static struct marker_entry *get_marker(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ u32 hash = jhash(name, strlen(name), 0);
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name))
+ return e;
+ }
+ return NULL;
+}
+
+/*
+ * Add the marker to the marker hash table. Must be called with markers_mutex
+ * held.
+ */
+static int add_marker(const char *name, const char *format,
+ marker_probe_func *probe, void *private)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ size_t name_len = strlen(name) + 1;
+ size_t format_len = 0;
+ u32 hash = jhash(name, name_len-1, 0);
+
+ if (format)
+ format_len = strlen(format) + 1;
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ printk(KERN_NOTICE
+ "Marker %s busy, probe %p already installed\n",
+ name, e->probe);
+ return -EBUSY; /* Already there */
+ }
+ }
+ /*
+ * Using kmalloc here to allocate a variable length element. Could
+ * cause some memory fragmentation if overused.
+ */
+ e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
+ GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], name, name_len);
+ if (format) {
+ e->format = &e->name[name_len];
+ memcpy(e->format, format, format_len);
+ trace_mark(core_marker_format, "name %s format %s",
+ e->name, e->format);
+ } else
+ e->format = NULL;
+ e->probe = probe;
+ e->private = private;
+ e->refcount = 0;
+ hlist_add_head(&e->hlist, head);
+ return 0;
+}
+
+/*
+ * Remove the marker from the marker hash table. Must be called with mutex_lock
+ * held.
+ */
+static void *remove_marker(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ int found = 0;
+ size_t len = strlen(name) + 1;
+ void *private = NULL;
+ u32 hash = jhash(name, len-1, 0);
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ private = e->private;
+ hlist_del(&e->hlist);
+ kfree(e);
+ }
+ return private;
+}
+
+/*
+ * Set the mark_entry format to the format found in the element.
+ */
+static int marker_set_format(struct marker_entry **entry, const char *format)
+{
+ struct marker_entry *e;
+ size_t name_len = strlen((*entry)->name) + 1;
+ size_t format_len = strlen(format) + 1;
+
+ e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
+ GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], (*entry)->name, name_len);
+ e->format = &e->name[name_len];
+ memcpy(e->format, format, format_len);
+ e->probe = (*entry)->probe;
+ e->private = (*entry)->private;
+ e->refcount = (*entry)->refcount;
+ hlist_add_before(&e->hlist, &(*entry)->hlist);
+ hlist_del(&(*entry)->hlist);
+ kfree(*entry);
+ *entry = e;
+ trace_mark(core_marker_format, "name %s format %s",
+ e->name, e->format);
+ return 0;
+}
+
+/*
+ * Sets the probe callback corresponding to one marker.
+ */
+static int set_marker(struct marker_entry **entry,
+ struct __mark_marker *elem)
+{
+ int ret;
+ WARN_ON(strcmp((*entry)->name, elem->name) != 0);
+
+ if ((*entry)->format) {
+ if (strcmp((*entry)->format, elem->format) != 0) {
+ printk(KERN_NOTICE
+ "Format mismatch for probe %s "
+ "(%s), marker (%s)\n",
+ (*entry)->name,
+ (*entry)->format,
+ elem->format);
+ return -EPERM;
+ }
+ } else {
+ ret = marker_set_format(entry, elem->format);
+ if (ret)
+ return ret;
+ }
+ elem->call = (*entry)->probe;
+ elem->private = (*entry)->private;
+ elem->state = 1;
+ return 0;
+}
+
+/*
+ * Disable a marker and its probe callback.
+ * Note: only after a synchronize_sched() issued after setting elem->call to the
+ * empty function insures that the original callback is not used anymore. This
+ * insured by preemption disabling around the call site.
+ */
+static void disable_marker(struct __mark_marker *elem)
+{
+ elem->state = 0;
+ elem->call = __mark_empty_function;
+ /*
+ * Leave the private data and id there, because removal is racy and
+ * should be done only after a synchronize_sched(). These are never used
+ * until the next initialization anyway.
+ */
+}
+
+/**
+ * marker_update_probe_range - Update a probe range
+ * @begin: beginning of the range
+ * @end: end of the range
+ * @probe_module: module address of the probe being updated
+ * @refcount: number of references left to the given probe_module (out)
+ *
+ * Updates the probe callback corresponding to a range of markers.
+ * Must be called with markers_mutex held.
+ */
+void marker_update_probe_range(struct __mark_marker *begin,
+ struct __mark_marker *end, struct module *probe_module,
+ int *refcount)
+{
+ struct __mark_marker *iter;
+ struct marker_entry *mark_entry;
+
+ for (iter = begin; iter < end; iter++) {
+ mark_entry = get_marker(iter->name);
+ if (mark_entry && mark_entry->refcount) {
+ set_marker(&mark_entry, iter);
+ /*
+ * ignore error, continue
+ */
+ if (probe_module)
+ if (probe_module ==
+ __module_text_address((unsigned long)mark_entry->probe))
+ (*refcount)++;
+ } else {
+ disable_marker(iter);
+ }
+ }
+}
+
+/*
+ * Update probes, removing the faulty probes.
+ * Issues a synchronize_sched() when no reference to the module passed
+ * as parameter is found in the probes so the probe module can be
+ * safely unloaded from now on.
+ */
+static void marker_update_probes(struct module *probe_module)
+{
+ int refcount = 0;
+
+ mutex_lock(&markers_mutex);
+ /* Core kernel markers */
+ marker_update_probe_range(__start___markers,
+ __stop___markers, probe_module, &refcount);
+ /* Markers in modules. */
+ module_update_markers(probe_module, &refcount);
+ if (probe_module && refcount == 0) {
+ synchronize_sched();
+ deferred_sync = 0;
+ }
+ mutex_unlock(&markers_mutex);
+}
+
+/**
+ * marker_probe_register - Connect a probe to a marker
+ * @name: marker name
+ * @format: format string
+ * @probe: probe handler
+ * @private: probe private data
+ *
+ * private data must be a valid allocated memory address, or NULL.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_probe_register(const char *name, const char *format,
+ marker_probe_func *probe, void *private)
+{
+ struct marker_entry *entry;
+ int ret = 0, need_update = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (entry && entry->refcount) {
+ ret = -EBUSY;
+ goto end;
+ }
+ if (deferred_sync) {
+ synchronize_sched();
+ deferred_sync = 0;
+ }
+ ret = add_marker(name, format, probe, private);
+ if (ret)
+ goto end;
+ need_update = 1;
+end:
+ mutex_unlock(&markers_mutex);
+ if (need_update)
+ marker_update_probes(NULL);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_probe_register);
+
+/**
+ * marker_probe_unregister - Disconnect a probe from a marker
+ * @name: marker name
+ *
+ * Returns the private data given to marker_probe_register, or an ERR_PTR().
+ */
+void *marker_probe_unregister(const char *name)
+{
+ struct module *probe_module;
+ struct marker_entry *entry;
+ void *private;
+ int need_update = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ private = ERR_PTR(-ENOENT);
+ goto end;
+ }
+ entry->refcount = 0;
+ /* In what module is the probe handler ? */
+ probe_module = __module_text_address((unsigned long)entry->probe);
+ private = remove_marker(name);
+ deferred_sync = 1;
+ need_update = 1;
+end:
+ mutex_unlock(&markers_mutex);
+ if (need_update)
+ marker_update_probes(probe_module);
+ return private;
+}
+EXPORT_SYMBOL_GPL(marker_probe_unregister);
+
+/**
+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
+ * @private: probe private data
+ *
+ * Unregister a marker by providing the registered private data.
+ * Returns the private data given to marker_probe_register, or an ERR_PTR().
+ */
+void *marker_probe_unregister_private_data(void *private)
+{
+ struct module *probe_module;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *entry;
+ int found = 0;
+ unsigned int i;
+ int need_update = 0;
+
+ mutex_lock(&markers_mutex);
+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
+ head = &marker_table[i];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (entry->private == private) {
+ found = 1;
+ goto iter_end;
+ }
+ }
+ }
+iter_end:
+ if (!found) {
+ private = ERR_PTR(-ENOENT);
+ goto end;
+ }
+ entry->refcount = 0;
+ /* In what module is the probe handler ? */
+ probe_module = __module_text_address((unsigned long)entry->probe);
+ private = remove_marker(entry->name);
+ deferred_sync = 1;
+ need_update = 1;
+end:
+ mutex_unlock(&markers_mutex);
+ if (need_update)
+ marker_update_probes(probe_module);
+ return private;
+}
+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
+
+/**
+ * marker_arm - Arm a marker
+ * @name: marker name
+ *
+ * Activate a marker. It keeps a reference count of the number of
+ * arming/disarming done.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_arm(const char *name)
+{
+ struct marker_entry * entry;
+ int ret = 0, need_update = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ ret = -ENOENT;
+ goto end;
+ }
+ /*
+ * Only need to update probes when refcount passes from 0 to 1.
+ */
+ if (entry->refcount++)
+ goto end;
+ need_update = 1;
+end:
+ mutex_unlock(&markers_mutex);
+ if (need_update)
+ marker_update_probes(NULL);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_arm);
+
+/**
+ * marker_disarm - Disarm a marker
+ * @name: marker name
+ *
+ * Disarm a marker. It keeps a reference count of the number of arming/disarming
+ * done.
+ * Returns 0 if ok, error value on error.
+ */
+int marker_disarm(const char *name)
+{
+ struct marker_entry * entry;
+ int ret = 0, need_update = 0;
+
+ mutex_lock(&markers_mutex);
+ entry = get_marker(name);
+ if (!entry) {
+ ret = -ENOENT;
+ goto end;
+ }
+ /*
+ * Only permit decrement refcount if higher than 0.
+ * Do probe update only on 1 -> 0 transition.
+ */
+ if (entry->refcount) {
+ if (--entry->refcount)
+ goto end;
+ } else {
+ ret = -EPERM;
+ goto end;
+ }
+ need_update = 1;
+end:
+ mutex_unlock(&markers_mutex);
+ if (need_update)
+ marker_update_probes(NULL);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(marker_disarm);
+
+/**
+ * marker_get_private_data - Get a marker's probe private data
+ * @name: marker name
+ *
+ * Returns the private data pointer, or an ERR_PTR.
+ * The private data pointer should _only_ be dereferenced if the caller is the
+ * owner of the data, or its content could vanish. This is mostly used to
+ * confirm that a caller is the owner of a registered probe.
+ */
+void *marker_get_private_data(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct marker_entry *e;
+ size_t name_len = strlen(name) + 1;
+ u32 hash = jhash(name, name_len-1, 0);
+ int found = 0;
+
+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ return e->private;
+ }
+ }
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(marker_get_private_data);
Index: linux-2.6-lttng/kernel/Kconfig.instrumentation
===================================================================
--- linux-2.6-lttng.orig/kernel/Kconfig.instrumentation 2007-09-25 07:18:40.000000000 -0400
+++ linux-2.6-lttng/kernel/Kconfig.instrumentation 2007-09-25 07:18:50.000000000 -0400
@@ -40,4 +40,10 @@ config KPROBES
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
+config MARKERS
+ bool "Activate markers"
+ help
+ Place an empty function call at each marker site. Can be
+ dynamically changed for a probe function.
+
endif # INSTRUMENTATION
Index: linux-2.6-lttng/kernel/Makefile
===================================================================
--- linux-2.6-lttng.orig/kernel/Makefile 2007-09-25 07:17:49.000000000 -0400
+++ linux-2.6-lttng/kernel/Makefile 2007-09-25 07:18:50.000000000 -0400
@@ -61,6 +61,7 @@ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
+obj-$(CONFIG_MARKERS) += marker.o
ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
# According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
On Fri, 2007-09-28 at 10:28 -0400, Mathieu Desnoyers wrote:
> +struct __mark_marker;
Hi Mathieu,
How about, "struct marker". You've taken the "marker*" namespace, so
all these underscores are __gratuitious__ :)
> +/*
> + * module_mutex nests inside markers_mutex. Markers mutex protects the builtin
> + * and module markers, the hash table and deferred_sync.
> + */
> +DEFINE_MUTEX(markers_mutex);
This can be static AFAICT.
The rest looks fine.
Cheers,
Rusty.
Linux Kernel Markers - Coding Style Fixes
- Use struct marker instead of struct __mark_marker.
- Change a "private_data" parameter name for "private".
- DEFINE_MUTEX(markers_mutex) is made static.
This patch applies after linux-kernel-markers.patch.
Signed-off-by: Mathieu Desnoyers <[email protected]>
CC: Rusty Russell <[email protected]>
---
include/linux/marker.h | 18 +++++++++---------
include/linux/module.h | 2 +-
kernel/marker.c | 22 ++++++++++------------
3 files changed, 20 insertions(+), 22 deletions(-)
Index: linux-2.6-lttng/include/linux/marker.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/marker.h 2007-09-30 09:33:48.000000000 -0400
+++ linux-2.6-lttng/include/linux/marker.h 2007-09-30 09:35:13.000000000 -0400
@@ -15,11 +15,11 @@
#include <linux/types.h>
struct module;
-struct __mark_marker;
+struct marker;
/**
* marker_probe_func - Type of a marker probe function
- * @mdata: pointer of type struct __mark_marker
+ * @mdata: pointer of type struct marker
* @private_data: caller site private data
* @fmt: format string
* @...: variable argument list
@@ -27,10 +27,10 @@ struct __mark_marker;
* Type of marker probe functions. They receive the mdata and need to parse the
* format string to recover the variable argument list.
*/
-typedef void marker_probe_func(const struct __mark_marker *mdata,
+typedef void marker_probe_func(const struct marker *mdata,
void *private_data, const char *fmt, ...);
-struct __mark_marker {
+struct marker {
const char *name; /* Marker name */
const char *format; /* Marker format string, describing the
* variable argument list.
@@ -57,7 +57,7 @@ struct __mark_marker {
static const char __mstrtab_format_##name[] \
__attribute__((section("__markers_strings"))) \
= format; \
- static struct __mark_marker __mark_##name \
+ static struct marker __mark_##name \
__attribute__((section("__markers"))) = \
{ __mstrtab_name_##name, __mstrtab_format_##name, \
0, __mark_empty_function, NULL }; \
@@ -72,13 +72,13 @@ struct __mark_marker {
} \
} while (0)
-extern void marker_update_probe_range(struct __mark_marker *begin,
- struct __mark_marker *end, struct module *probe_module, int *refcount);
+extern void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module, int *refcount);
#else /* !CONFIG_MARKERS */
#define __trace_mark(name, call_data, format, args...) \
__mark_check_format(format, ## args)
-static inline void marker_update_probe_range(struct __mark_marker *begin,
- struct __mark_marker *end, struct module *probe_module, int *refcount)
+static inline void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module, int *refcount)
{ }
#endif /* CONFIG_MARKERS */
Index: linux-2.6-lttng/include/linux/module.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/module.h 2007-09-30 09:35:26.000000000 -0400
+++ linux-2.6-lttng/include/linux/module.h 2007-09-30 09:35:35.000000000 -0400
@@ -372,7 +372,7 @@ struct module
keeping pointers to this stuff */
char *args;
#ifdef CONFIG_MARKERS
- struct __mark_marker *markers;
+ struct marker *markers;
unsigned int num_markers;
#endif
};
Index: linux-2.6-lttng/kernel/marker.c
===================================================================
--- linux-2.6-lttng.orig/kernel/marker.c 2007-09-30 09:35:48.000000000 -0400
+++ linux-2.6-lttng/kernel/marker.c 2007-09-30 09:44:14.000000000 -0400
@@ -24,14 +24,14 @@
#include <linux/marker.h>
#include <linux/err.h>
-extern struct __mark_marker __start___markers[];
-extern struct __mark_marker __stop___markers[];
+extern struct marker __start___markers[];
+extern struct marker __stop___markers[];
/*
* module_mutex nests inside markers_mutex. Markers mutex protects the builtin
* and module markers, the hash table and deferred_sync.
*/
-DEFINE_MUTEX(markers_mutex);
+static DEFINE_MUTEX(markers_mutex);
/*
* Marker deferred synchronization.
@@ -63,7 +63,7 @@ static struct hlist_head marker_table[MA
/**
* __mark_empty_function - Empty probe callback
- * @mdata: pointer of type const struct __mark_marker
+ * @mdata: pointer of type const struct marker
* @fmt: format string
* @...: variable argument list
*
@@ -72,8 +72,7 @@ static struct hlist_head marker_table[MA
* though the function pointer change and the marker enabling are two distinct
* operations that modifies the execution flow of preemptible code.
*/
-void __mark_empty_function(const struct __mark_marker *mdata,
- void *private_data,
+void __mark_empty_function(const struct marker *mdata, void *private,
const char *fmt, ...)
{
}
@@ -207,8 +206,7 @@ static int marker_set_format(struct mark
/*
* Sets the probe callback corresponding to one marker.
*/
-static int set_marker(struct marker_entry **entry,
- struct __mark_marker *elem)
+static int set_marker(struct marker_entry **entry, struct marker *elem)
{
int ret;
WARN_ON(strcmp((*entry)->name, elem->name) != 0);
@@ -240,7 +238,7 @@ static int set_marker(struct marker_entr
* empty function insures that the original callback is not used anymore. This
* insured by preemption disabling around the call site.
*/
-static void disable_marker(struct __mark_marker *elem)
+static void disable_marker(struct marker *elem)
{
elem->state = 0;
elem->call = __mark_empty_function;
@@ -261,11 +259,11 @@ static void disable_marker(struct __mark
* Updates the probe callback corresponding to a range of markers.
* Must be called with markers_mutex held.
*/
-void marker_update_probe_range(struct __mark_marker *begin,
- struct __mark_marker *end, struct module *probe_module,
+void marker_update_probe_range(struct marker *begin,
+ struct marker *end, struct module *probe_module,
int *refcount)
{
- struct __mark_marker *iter;
+ struct marker *iter;
struct marker_entry *mark_entry;
for (iter = begin; iter < end; iter++) {
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
* Mathieu Desnoyers ([email protected]) wrote:
> Linux Kernel Markers - Coding Style Fixes
>
> - Use struct marker instead of struct __mark_marker.
> - Change a "private_data" parameter name for "private".
> - DEFINE_MUTEX(markers_mutex) is made static.
>
> This patch applies after linux-kernel-markers.patch.
>
Hi Andrew,
Just to be precise wrt what you have, it applies right after:
linux-kernel-markers-checkpatch-fixes.patch
in your series.
Mathieu
> Signed-off-by: Mathieu Desnoyers <[email protected]>
> CC: Rusty Russell <[email protected]>
> ---
> include/linux/marker.h | 18 +++++++++---------
> include/linux/module.h | 2 +-
> kernel/marker.c | 22 ++++++++++------------
> 3 files changed, 20 insertions(+), 22 deletions(-)
>
> Index: linux-2.6-lttng/include/linux/marker.h
> ===================================================================
> --- linux-2.6-lttng.orig/include/linux/marker.h 2007-09-30 09:33:48.000000000 -0400
> +++ linux-2.6-lttng/include/linux/marker.h 2007-09-30 09:35:13.000000000 -0400
> @@ -15,11 +15,11 @@
> #include <linux/types.h>
>
> struct module;
> -struct __mark_marker;
> +struct marker;
>
> /**
> * marker_probe_func - Type of a marker probe function
> - * @mdata: pointer of type struct __mark_marker
> + * @mdata: pointer of type struct marker
> * @private_data: caller site private data
> * @fmt: format string
> * @...: variable argument list
> @@ -27,10 +27,10 @@ struct __mark_marker;
> * Type of marker probe functions. They receive the mdata and need to parse the
> * format string to recover the variable argument list.
> */
> -typedef void marker_probe_func(const struct __mark_marker *mdata,
> +typedef void marker_probe_func(const struct marker *mdata,
> void *private_data, const char *fmt, ...);
>
> -struct __mark_marker {
> +struct marker {
> const char *name; /* Marker name */
> const char *format; /* Marker format string, describing the
> * variable argument list.
> @@ -57,7 +57,7 @@ struct __mark_marker {
> static const char __mstrtab_format_##name[] \
> __attribute__((section("__markers_strings"))) \
> = format; \
> - static struct __mark_marker __mark_##name \
> + static struct marker __mark_##name \
> __attribute__((section("__markers"))) = \
> { __mstrtab_name_##name, __mstrtab_format_##name, \
> 0, __mark_empty_function, NULL }; \
> @@ -72,13 +72,13 @@ struct __mark_marker {
> } \
> } while (0)
>
> -extern void marker_update_probe_range(struct __mark_marker *begin,
> - struct __mark_marker *end, struct module *probe_module, int *refcount);
> +extern void marker_update_probe_range(struct marker *begin,
> + struct marker *end, struct module *probe_module, int *refcount);
> #else /* !CONFIG_MARKERS */
> #define __trace_mark(name, call_data, format, args...) \
> __mark_check_format(format, ## args)
> -static inline void marker_update_probe_range(struct __mark_marker *begin,
> - struct __mark_marker *end, struct module *probe_module, int *refcount)
> +static inline void marker_update_probe_range(struct marker *begin,
> + struct marker *end, struct module *probe_module, int *refcount)
> { }
> #endif /* CONFIG_MARKERS */
>
> Index: linux-2.6-lttng/include/linux/module.h
> ===================================================================
> --- linux-2.6-lttng.orig/include/linux/module.h 2007-09-30 09:35:26.000000000 -0400
> +++ linux-2.6-lttng/include/linux/module.h 2007-09-30 09:35:35.000000000 -0400
> @@ -372,7 +372,7 @@ struct module
> keeping pointers to this stuff */
> char *args;
> #ifdef CONFIG_MARKERS
> - struct __mark_marker *markers;
> + struct marker *markers;
> unsigned int num_markers;
> #endif
> };
> Index: linux-2.6-lttng/kernel/marker.c
> ===================================================================
> --- linux-2.6-lttng.orig/kernel/marker.c 2007-09-30 09:35:48.000000000 -0400
> +++ linux-2.6-lttng/kernel/marker.c 2007-09-30 09:44:14.000000000 -0400
> @@ -24,14 +24,14 @@
> #include <linux/marker.h>
> #include <linux/err.h>
>
> -extern struct __mark_marker __start___markers[];
> -extern struct __mark_marker __stop___markers[];
> +extern struct marker __start___markers[];
> +extern struct marker __stop___markers[];
>
> /*
> * module_mutex nests inside markers_mutex. Markers mutex protects the builtin
> * and module markers, the hash table and deferred_sync.
> */
> -DEFINE_MUTEX(markers_mutex);
> +static DEFINE_MUTEX(markers_mutex);
>
> /*
> * Marker deferred synchronization.
> @@ -63,7 +63,7 @@ static struct hlist_head marker_table[MA
>
> /**
> * __mark_empty_function - Empty probe callback
> - * @mdata: pointer of type const struct __mark_marker
> + * @mdata: pointer of type const struct marker
> * @fmt: format string
> * @...: variable argument list
> *
> @@ -72,8 +72,7 @@ static struct hlist_head marker_table[MA
> * though the function pointer change and the marker enabling are two distinct
> * operations that modifies the execution flow of preemptible code.
> */
> -void __mark_empty_function(const struct __mark_marker *mdata,
> - void *private_data,
> +void __mark_empty_function(const struct marker *mdata, void *private,
> const char *fmt, ...)
> {
> }
> @@ -207,8 +206,7 @@ static int marker_set_format(struct mark
> /*
> * Sets the probe callback corresponding to one marker.
> */
> -static int set_marker(struct marker_entry **entry,
> - struct __mark_marker *elem)
> +static int set_marker(struct marker_entry **entry, struct marker *elem)
> {
> int ret;
> WARN_ON(strcmp((*entry)->name, elem->name) != 0);
> @@ -240,7 +238,7 @@ static int set_marker(struct marker_entr
> * empty function insures that the original callback is not used anymore. This
> * insured by preemption disabling around the call site.
> */
> -static void disable_marker(struct __mark_marker *elem)
> +static void disable_marker(struct marker *elem)
> {
> elem->state = 0;
> elem->call = __mark_empty_function;
> @@ -261,11 +259,11 @@ static void disable_marker(struct __mark
> * Updates the probe callback corresponding to a range of markers.
> * Must be called with markers_mutex held.
> */
> -void marker_update_probe_range(struct __mark_marker *begin,
> - struct __mark_marker *end, struct module *probe_module,
> +void marker_update_probe_range(struct marker *begin,
> + struct marker *end, struct module *probe_module,
> int *refcount)
> {
> - struct __mark_marker *iter;
> + struct marker *iter;
> struct marker_entry *mark_entry;
>
> for (iter = begin; iter < end; iter++) {
> --
> Mathieu Desnoyers
> Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
> OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Change struct marker users
Prior to use struct marker in the linux kernel markers, we need to clean
two drivers which use this structure name.
Change bonding driver types :
- struct marker to struct bond_marker.
- marker_t to bond_marker_t.
- marker_header to bond_marker_header.
- marker_header_t to bond_marker_header_t.
Change qla4xxx struct marker_entry usage :
- Change struct marker_entry for struct qla4_marker_entry.
This patch applies before the
linux-kernel-markers-coding-style-fix.patch.
Signed-off-by: Mathieu Desnoyers <[email protected]>
---
drivers/net/bonding/bond_3ad.c | 32 +++++++++++++++++---------------
drivers/net/bonding/bond_3ad.h | 12 ++++++------
drivers/scsi/qla4xxx/ql4_fw.h | 2 +-
drivers/scsi/qla4xxx/ql4_iocb.c | 2 +-
4 files changed, 25 insertions(+), 23 deletions(-)
Index: linux-2.6-lttng/drivers/scsi/qla4xxx/ql4_fw.h
===================================================================
--- linux-2.6-lttng.orig/drivers/scsi/qla4xxx/ql4_fw.h 2007-10-01 11:23:57.000000000 -0400
+++ linux-2.6-lttng/drivers/scsi/qla4xxx/ql4_fw.h 2007-10-01 11:26:23.000000000 -0400
@@ -671,7 +671,7 @@ struct continuation_t1_entry {
#define ET_CONTINUE ET_CONT_T1
/* Marker entry structure*/
-struct marker_entry {
+struct qla4_marker_entry {
struct qla4_header hdr; /* 00-03 */
uint32_t system_defined; /* 04-07 */
Index: linux-2.6-lttng/drivers/scsi/qla4xxx/ql4_iocb.c
===================================================================
--- linux-2.6-lttng.orig/drivers/scsi/qla4xxx/ql4_iocb.c 2007-10-01 11:24:05.000000000 -0400
+++ linux-2.6-lttng/drivers/scsi/qla4xxx/ql4_iocb.c 2007-10-01 11:26:30.000000000 -0400
@@ -69,7 +69,7 @@ static int qla4xxx_get_req_pkt(struct sc
static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun)
{
- struct marker_entry *marker_entry;
+ struct qla4_marker_entry *marker_entry;
unsigned long flags = 0;
uint8_t status = QLA_SUCCESS;
Index: linux-2.6-lttng/drivers/net/bonding/bond_3ad.c
===================================================================
--- linux-2.6-lttng.orig/drivers/net/bonding/bond_3ad.c 2007-10-01 11:23:33.000000000 -0400
+++ linux-2.6-lttng/drivers/net/bonding/bond_3ad.c 2007-10-01 11:31:37.000000000 -0400
@@ -126,7 +126,7 @@ static struct aggregator *__get_active_a
// ================= main 802.3ad protocol functions ==================
static int ad_lacpdu_send(struct port *port);
-static int ad_marker_send(struct port *port, struct marker *marker);
+static int ad_marker_send(struct port *port, struct bond_marker *marker);
static void ad_mux_machine(struct port *port);
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
static void ad_tx_machine(struct port *port);
@@ -139,8 +139,8 @@ static void ad_initialize_port(struct po
static void ad_initialize_lacpdu(struct lacpdu *Lacpdu);
static void ad_enable_collecting_distributing(struct port *port);
static void ad_disable_collecting_distributing(struct port *port);
-static void ad_marker_info_received(struct marker *marker_info, struct port *port);
-static void ad_marker_response_received(struct marker *marker, struct port *port);
+static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port);
+static void ad_marker_response_received(struct bond_marker *marker, struct port *port);
/////////////////////////////////////////////////////////////////////////////////
@@ -889,12 +889,12 @@ static int ad_lacpdu_send(struct port *p
* Returns: 0 on success
* < 0 on error
*/
-static int ad_marker_send(struct port *port, struct marker *marker)
+static int ad_marker_send(struct port *port, struct bond_marker *marker)
{
struct slave *slave = port->slave;
struct sk_buff *skb;
- struct marker_header *marker_header;
- int length = sizeof(struct marker_header);
+ struct bond_marker_header *marker_header;
+ int length = sizeof(struct bond_marker_header);
struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
skb = dev_alloc_skb(length + 16);
@@ -909,7 +909,7 @@ static int ad_marker_send(struct port *p
skb->network_header = skb->mac_header + ETH_HLEN;
skb->protocol = PKT_TYPE_LACPDU;
- marker_header = (struct marker_header *)skb_put(skb, length);
+ marker_header = (struct bond_marker_header *)skb_put(skb, length);
marker_header->ad_header.destination_address = lacpdu_multicast_address;
/* Note: source addres is set to be the member's PERMANENT address, because we use it
@@ -1709,7 +1709,7 @@ static void ad_disable_collecting_distri
*/
static void ad_marker_info_send(struct port *port)
{
- struct marker marker;
+ struct bond_marker marker;
u16 index;
// fill the marker PDU with the appropriate values
@@ -1742,13 +1742,14 @@ static void ad_marker_info_send(struct p
* @port: the port we're looking at
*
*/
-static void ad_marker_info_received(struct marker *marker_info,struct port *port)
+static void ad_marker_info_received(struct bond_marker *marker_info,
+ struct port *port)
{
- struct marker marker;
+ struct bond_marker marker;
// copy the received marker data to the response marker
//marker = *marker_info;
- memcpy(&marker, marker_info, sizeof(struct marker));
+ memcpy(&marker, marker_info, sizeof(struct bond_marker));
// change the marker subtype to marker response
marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
// send the marker response
@@ -1767,7 +1768,8 @@ static void ad_marker_info_received(stru
* response for marker PDU's, in this stage, but only to respond to marker
* information.
*/
-static void ad_marker_response_received(struct marker *marker, struct port *port)
+static void ad_marker_response_received(struct bond_marker *marker,
+ struct port *port)
{
marker=NULL; // just to satisfy the compiler
port=NULL; // just to satisfy the compiler
@@ -2164,15 +2166,15 @@ static void bond_3ad_rx_indication(struc
case AD_TYPE_MARKER:
// No need to convert fields to Little Endian since we don't use the marker's fields.
- switch (((struct marker *)lacpdu)->tlv_type) {
+ switch (((struct bond_marker *)lacpdu)->tlv_type) {
case AD_MARKER_INFORMATION_SUBTYPE:
dprintk("Received Marker Information on port %d\n", port->actor_port_number);
- ad_marker_info_received((struct marker *)lacpdu, port);
+ ad_marker_info_received((struct bond_marker *)lacpdu, port);
break;
case AD_MARKER_RESPONSE_SUBTYPE:
dprintk("Received Marker Response on port %d\n", port->actor_port_number);
- ad_marker_response_received((struct marker *)lacpdu, port);
+ ad_marker_response_received((struct bond_marker *)lacpdu, port);
break;
default:
Index: linux-2.6-lttng/drivers/net/bonding/bond_3ad.h
===================================================================
--- linux-2.6-lttng.orig/drivers/net/bonding/bond_3ad.h 2007-10-01 11:23:50.000000000 -0400
+++ linux-2.6-lttng/drivers/net/bonding/bond_3ad.h 2007-10-01 11:28:54.000000000 -0400
@@ -92,7 +92,7 @@ typedef enum {
typedef enum {
AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
AD_MARKER_RESPONSE_SUBTYPE // marker response subtype
-} marker_subtype_t;
+} bond_marker_subtype_t;
// timers types(43.4.9 in the 802.3ad standard)
typedef enum {
@@ -148,7 +148,7 @@ typedef struct lacpdu_header {
} lacpdu_header_t;
// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
-typedef struct marker {
+typedef struct bond_marker {
u8 subtype; // = 0x02 (marker PDU)
u8 version_number; // = 0x01
u8 tlv_type; // = 0x01 (marker information)
@@ -161,12 +161,12 @@ typedef struct marker {
u8 tlv_type_terminator; // = 0x00
u8 terminator_length; // = 0x00
u8 reserved_90[90]; // = 0
-} marker_t;
+} bond_marker_t;
-typedef struct marker_header {
+typedef struct bond_marker_header {
struct ad_header ad_header;
- struct marker marker;
-} marker_header_t;
+ struct bond_marker marker;
+} bond_marker_header_t;
#pragma pack()
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Linux Kernel Markers - Alignment Fix
Fix the alignment of the struct marker declaration in the trace_mark() macro.
Otherwise, we run into problems on 64 bits architectures where the struct marker
structure is bigger than 32 bytes : gcc becomes alignment-happy and align these
structures on 32 bytes while the iteration on the markers is itself only aligned
on 8 bytes, as specified by the type attribute. Specifying the alignmentof the
type only is not enough to restrain gcc happiness; we must specify a variable
alignment attribute too.
This bug causes NULL pointer dereference at module load time on x86_64
when we load marker-example.ko.
Thanks to Mike Mason for reporting this.
It applies to 2.6.23-rc8-mm2, after the linux kernel markers coding style
fixes. This is an important bugfix that should be merged with the
markers.
Signed-off-by: Mathieu Desnoyers <[email protected]>
CC: Christoph Hellwig <[email protected]>
CC: Mike Mason <[email protected]>
CC: "Frank Ch. Eigler" <[email protected]>
---
include/linux/marker.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-2.6-lttng/include/linux/marker.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/marker.h 2007-10-02 07:33:21.000000000 -0400
+++ linux-2.6-lttng/include/linux/marker.h 2007-10-02 07:33:58.000000000 -0400
@@ -58,7 +58,7 @@ struct marker {
__attribute__((section("__markers_strings"))) \
= format; \
static struct marker __mark_##name \
- __attribute__((section("__markers"))) = \
+ __attribute__((section("__markers"), aligned(8))) = \
{ __mstrtab_name_##name, __mstrtab_format_##name, \
0, __mark_empty_function, NULL }; \
asm volatile ("" : : "i" (&__mark_##name)); \
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68