* [RFC patch 0/3] Tracepoints
@ 2008-07-03 16:05 Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 1/3] Kernel Tracepoints Mathieu Desnoyers
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Mathieu Desnoyers @ 2008-07-03 16:05 UTC (permalink / raw)
To: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Masami Hiramatsu
Hi,
Here is the new tracepoint infrastructure, heavily inspired from the Markers. It
applies on 2.6.26-rc8. I also post my fs/ LTTng instrumentation as an example
of the resulting code using tracepoints. Please feel free to comment.
- Tracepoints allow more complete type checking (at compile-time) than markers.
- They allow to connect probes involving in-kernel tracers which must be aware
of complex types such as "struct task_struct *" (not just a void *).
- They are not meant as a replacement for markers, since they do not allow
one-liner printk-style addition of tracing statements for debugging purpose.
- They require a declaration in a header file, which creates a nice stable API.
Thanks,
Mathieu
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC patch 1/3] Kernel Tracepoints
2008-07-03 16:05 [RFC patch 0/3] Tracepoints Mathieu Desnoyers
@ 2008-07-03 16:05 ` Mathieu Desnoyers
2008-07-03 21:47 ` Masami Hiramatsu
2008-07-03 16:05 ` [RFC patch 2/3] LTTng tracepoint instrumentation fs Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 3/3] LTTng instrumentation FS tracepoint probes Mathieu Desnoyers
2 siblings, 1 reply; 6+ messages in thread
From: Mathieu Desnoyers @ 2008-07-03 16:05 UTC (permalink / raw)
To: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Masami Hiramatsu
Cc: Mathieu Desnoyers, Frank Ch. Eigler, Hideo AOKI, Takashi Nishiie,
Steven Rostedt, Alexander Viro
[-- Attachment #1: tracepoints.patch --]
[-- Type: text/plain, Size: 27533 bytes --]
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
Allows complete typing verification. No format string required.
TODO : Documentation/tracepoint.txt
Changelog :
- Use #name ":" #proto as string to identify the tracepoint in the
tracepoint table. This will make sure not type mismatch happens due to
connexion of a probe with the wrong type to a tracepoint declared with
the same name in a different header.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: 'Peter Zijlstra' <peterz@infradead.org>
CC: "Frank Ch. Eigler" <fche@redhat.com>
CC: 'Ingo Molnar' <mingo@elte.hu>
CC: 'Hideo AOKI' <haoki@redhat.com>
CC: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
CC: 'Steven Rostedt' <rostedt@goodmis.org>
CC: Alexander Viro <viro@zeniv.linux.org.uk>
---
include/asm-generic/vmlinux.lds.h | 6
include/linux/module.h | 17 +
include/linux/tracepoint.h | 139 ++++++++++
init/Kconfig | 16 +
kernel/Makefile | 1
kernel/module.c | 66 ++++-
kernel/tracepoint.c | 498 ++++++++++++++++++++++++++++++++++++++
7 files changed, 741 insertions(+), 2 deletions(-)
Index: linux-2.6-lttng/init/Kconfig
===================================================================
--- linux-2.6-lttng.orig/init/Kconfig 2008-07-03 11:47:15.000000000 -0400
+++ linux-2.6-lttng/init/Kconfig 2008-07-03 11:49:54.000000000 -0400
@@ -782,12 +782,28 @@ config PROFILING
Say Y here to enable the extended profiling support mechanisms used
by profilers such as OProfile.
+config TRACEPOINTS
+ bool "Activate tracepoints"
+ default y
+ help
+ Place an empty function call at each tracepoint site. Can be
+ dynamically changed for a probe function.
+
config MARKERS
bool "Activate markers"
help
Place an empty function call at each marker site. Can be
dynamically changed for a probe function.
+config TRACEPROBES
+ tristate "Compile generic tracing probes"
+ depends on MARKERS
+ default y
+ help
+ Compile generic tracing probes, which connect to the tracepoints when
+ loaded and format the information collected by the tracepoints with
+ the Markers.
+
source "arch/Kconfig"
config PROC_PAGE_MONITOR
Index: linux-2.6-lttng/kernel/Makefile
===================================================================
--- linux-2.6-lttng.orig/kernel/Makefile 2008-07-03 11:47:15.000000000 -0400
+++ linux-2.6-lttng/kernel/Makefile 2008-07-03 11:49:54.000000000 -0400
@@ -68,6 +68,7 @@ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_MARKERS) += marker.o
+obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
Index: linux-2.6-lttng/include/linux/tracepoint.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/include/linux/tracepoint.h 2008-07-03 11:49:54.000000000 -0400
@@ -0,0 +1,139 @@
+#ifndef _LINUX_TRACEPOINT_H
+#define _LINUX_TRACEPOINT_H
+
+/*
+ * Kernel Tracepoint API.
+ *
+ * See Documentation/tracepoint.txt.
+ *
+ * (C) Copyright 2008 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ *
+ * Heavily inspired from the Linux Kernel Markers.
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+
+struct module;
+struct tracepoint;
+
+struct tracepoint_probe_closure {
+ void *func; /* Callback */
+ void *probe_private; /* Private probe data */
+};
+
+struct tracepoint {
+ const char *name; /* Tracepoint name */
+ int state; /* State. */
+ struct tracepoint_probe_closure *multi; /* Closures */
+} __attribute__((aligned(8)));
+
+
+#define TPPROTO(args...) args
+#define TPARGS(args...) args
+
+#ifdef CONFIG_TRACEPOINTS
+
+/*
+ * 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 __tracepoints 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 DEFINE_TRACE(name, proto, args) \
+ static inline void _do_trace_##name(struct tracepoint *tp, proto) \
+ { \
+ int i; \
+ struct tracepoint_probe_closure *multi; \
+ preempt_disable(); \
+ multi = tp->multi; \
+ smp_read_barrier_depends(); \
+ if (multi) { \
+ for (i = 0; multi[i].func; i++) { \
+ ((void(*)(void *private_data, proto)) \
+ (multi[i].func))(multi[i].probe_private, args);\
+ } \
+ } \
+ preempt_enable(); \
+ } \
+ static inline void trace_##name(proto) \
+ { \
+ static const char __tpstrtab_##name[] \
+ __attribute__((section("__tracepoints_strings"))) \
+ = #name ":" #proto; \
+ static struct tracepoint __tracepoint_##name \
+ __attribute__((section("__tracepoints"), aligned(8))) = \
+ { __tpstrtab_##name, 0, NULL }; \
+ if (unlikely(__tracepoint_##name.state)) \
+ _do_trace_##name(&__tracepoint_##name, args); \
+ } \
+ static inline int register_trace_##name( \
+ void (*probe)(void *private_data, proto), \
+ void *private_data) \
+ { \
+ return tracepoint_probe_register(#name ":" #proto, \
+ (void *)probe, private_data); \
+ } \
+ static inline void unregister_trace_##name( \
+ void (*probe)(void *private_data, proto), \
+ void *private_data) \
+ { \
+ tracepoint_probe_unregister(#name ":" #proto, \
+ (void *)probe, private_data); \
+ }
+
+extern void tracepoint_update_probe_range(struct tracepoint *begin,
+ struct tracepoint *end);
+
+#else /* !CONFIG_TRACEPOINTS */
+#define DEFINE_TRACE(name, proto, args) \
+ static inline void _do_trace_##name(struct tracepoint *tp, proto) \
+ { } \
+ static inline void trace_##name(proto) \
+ { } \
+ static inline int register_trace_##name( \
+ void (*probe)(void *private_data, proto), \
+ void *private_data) \
+ { \
+ return -ENOSYS; \
+ } \
+ static inline void unregister_trace_##name( \
+ void (*probe)(void *private_data, proto), \
+ void *private_data) \
+ { }
+
+static inline void tracepoint_update_probe_range(struct tracepoint *begin,
+ struct tracepoint *end)
+{ }
+#endif /* CONFIG_TRACEPOINTS */
+
+/*
+ * Connect a probe to a tracepoint.
+ * Internal API, should not be used directly.
+ */
+extern int tracepoint_probe_register(const char *name,
+ void *probe, void *probe_private);
+
+/*
+ * Disconnect a probe from a tracepoint.
+ * Internal API, should not be used directly.
+ */
+extern int tracepoint_probe_unregister(const char *name,
+ void *probe, void *probe_private);
+
+struct tracepoint_iter {
+ struct module *module;
+ struct tracepoint *tracepoint;
+};
+
+extern void tracepoint_iter_start(struct tracepoint_iter *iter);
+extern void tracepoint_iter_next(struct tracepoint_iter *iter);
+extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
+extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
+extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
+ struct tracepoint *begin, struct tracepoint *end);
+
+#endif
Index: linux-2.6-lttng/include/asm-generic/vmlinux.lds.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-generic/vmlinux.lds.h 2008-07-03 11:47:15.000000000 -0400
+++ linux-2.6-lttng/include/asm-generic/vmlinux.lds.h 2008-07-03 11:49:54.000000000 -0400
@@ -52,7 +52,10 @@
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___markers) = .; \
*(__markers) \
- VMLINUX_SYMBOL(__stop___markers) = .;
+ VMLINUX_SYMBOL(__stop___markers) = .; \
+ VMLINUX_SYMBOL(__start___tracepoints) = .; \
+ *(__tracepoints) \
+ VMLINUX_SYMBOL(__stop___tracepoints) = .;
#define RO_DATA(align) \
. = ALIGN((align)); \
@@ -61,6 +64,7 @@
*(.rodata) *(.rodata.*) \
*(__vermagic) /* Kernel version magic */ \
*(__markers_strings) /* Markers: strings */ \
+ *(__tracepoints_strings)/* Tracepoints: strings */ \
} \
\
.rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
Index: linux-2.6-lttng/kernel/tracepoint.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/kernel/tracepoint.c 2008-07-03 11:54:30.000000000 -0400
@@ -0,0 +1,498 @@
+/*
+ * 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/tracepoint.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/immediate.h>
+
+extern struct tracepoint __start___tracepoints[];
+extern struct tracepoint __stop___tracepoints[];
+
+/* Set to 1 to enable tracepoint debug output */
+static const int tracepoint_debug;
+
+/*
+ * tracepoints_mutex nests inside module_mutex. Tracepoints mutex protects the
+ * builtin and module tracepoints and the hash table.
+ */
+static DEFINE_MUTEX(tracepoints_mutex);
+
+/*
+ * Tracepoint hash table, containing the active tracepoints.
+ * Protected by tracepoints_mutex.
+ */
+#define TRACEPOINT_HASH_BITS 6
+#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
+
+/*
+ * 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 tracepoint. It
+ * is also used to delay the free of multiple probes array until a quiescent
+ * state is reached.
+ * tracepoint entries modifications are protected by the tracepoints_mutex.
+ */
+struct tracepoint_entry {
+ struct hlist_node hlist;
+ struct tracepoint_probe_closure *multi;
+ int refcount; /* Number of times armed. 0 if disarmed. */
+ struct rcu_head rcu;
+ void *oldptr;
+ unsigned char rcu_pending:1;
+ char name[0];
+};
+
+static struct hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
+
+static void free_old_closure(struct rcu_head *head)
+{
+ struct tracepoint_entry *entry = container_of(head,
+ struct tracepoint_entry, rcu);
+ kfree(entry->oldptr);
+ /* Make sure we free the data before setting the pending flag to 0 */
+ smp_wmb();
+ entry->rcu_pending = 0;
+}
+
+static void debug_print_probes(struct tracepoint_entry *entry)
+{
+ int i;
+
+ if (!tracepoint_debug)
+ return;
+
+ for (i = 0; entry->multi[i].func; i++)
+ printk(KERN_DEBUG "Multi probe %d : %p %p\n", i,
+ entry->multi[i].func,
+ entry->multi[i].probe_private);
+}
+
+static struct tracepoint_probe_closure *
+tracepoint_entry_add_probe(struct tracepoint_entry *entry,
+ void *probe, void *probe_private)
+{
+ int nr_probes = 0;
+ struct tracepoint_probe_closure *old, *new;
+
+ WARN_ON(!probe);
+
+ debug_print_probes(entry);
+ old = entry->multi;
+ if (old) {
+ /* (N -> N+1), (N != 0, 1) probes */
+ for (nr_probes = 0; old[nr_probes].func; nr_probes++)
+ if (old[nr_probes].func == probe
+ && old[nr_probes].probe_private
+ == probe_private)
+ return ERR_PTR(-EBUSY);
+ }
+ /* + 2 : one for new probe, one for NULL func */
+ new = kzalloc((nr_probes + 2) * sizeof(struct tracepoint_probe_closure),
+ GFP_KERNEL);
+ if (new == NULL)
+ return ERR_PTR(-ENOMEM);
+ if (old)
+ memcpy(new, old,
+ nr_probes * sizeof(struct tracepoint_probe_closure));
+ new[nr_probes].func = probe;
+ new[nr_probes].probe_private = probe_private;
+ entry->refcount = nr_probes + 1;
+ entry->multi = new;
+ debug_print_probes(entry);
+ return old;
+}
+
+static struct tracepoint_probe_closure *
+tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
+ void *probe, void *probe_private)
+{
+ int nr_probes = 0, nr_del = 0, i;
+ struct tracepoint_probe_closure *old, *new;
+
+ old = entry->multi;
+
+ debug_print_probes(entry);
+ /* (N -> M), (N > 1, M >= 0) probes */
+ for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+ if ((!probe || old[nr_probes].func == probe)
+ && old[nr_probes].probe_private
+ == probe_private)
+ nr_del++;
+ }
+
+ if (nr_probes - nr_del == 0) {
+ /* N -> 0, (N > 1) */
+ entry->multi = NULL;
+ entry->refcount = 0;
+ debug_print_probes(entry);
+ return old;
+ } else {
+ int j = 0;
+ /* N -> M, (N > 1, M > 0) */
+ /* + 1 for NULL */
+ new = kzalloc((nr_probes - nr_del + 1)
+ * sizeof(struct tracepoint_probe_closure), GFP_KERNEL);
+ if (new == NULL)
+ return ERR_PTR(-ENOMEM);
+ for (i = 0; old[i].func; i++)
+ if ((probe && old[i].func != probe) ||
+ old[i].probe_private != probe_private)
+ new[j++] = old[i];
+ entry->refcount = nr_probes - nr_del;
+ entry->multi = new;
+ }
+ debug_print_probes(entry);
+ return old;
+}
+
+/*
+ * Get tracepoint if the tracepoint is present in the tracepoint hash table.
+ * Must be called with tracepoints_mutex held.
+ * Returns NULL if not present.
+ */
+static struct tracepoint_entry *get_tracepoint(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct tracepoint_entry *e;
+ u32 hash = jhash(name, strlen(name), 0);
+
+ head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name))
+ return e;
+ }
+ return NULL;
+}
+
+/*
+ * Add the tracepoint to the tracepoint hash table. Must be called with
+ * tracepoints_mutex held.
+ */
+static struct tracepoint_entry *add_tracepoint(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct tracepoint_entry *e;
+ size_t name_len = strlen(name) + 1;
+ u32 hash = jhash(name, name_len-1, 0);
+
+ head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ printk(KERN_NOTICE
+ "tracepoint %s busy\n", name);
+ return ERR_PTR(-EBUSY); /* Already there */
+ }
+ }
+ /*
+ * Using kmalloc here to allocate a variable length element. Could
+ * cause some memory fragmentation if overused.
+ */
+ e = kmalloc(sizeof(struct tracepoint_entry) + name_len, GFP_KERNEL);
+ if (!e)
+ return ERR_PTR(-ENOMEM);
+ memcpy(&e->name[0], name, name_len);
+ e->multi = NULL;
+ e->refcount = 0;
+ e->rcu_pending = 0;
+ hlist_add_head(&e->hlist, head);
+ return e;
+}
+
+/*
+ * Remove the tracepoint from the tracepoint hash table. Must be called with
+ * mutex_lock held.
+ */
+static int remove_tracepoint(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct tracepoint_entry *e;
+ int found = 0;
+ size_t len = strlen(name) + 1;
+ u32 hash = jhash(name, len-1, 0);
+
+ head = &tracepoint_table[hash & ((1 << TRACEPOINT_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist) {
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return -ENOENT;
+ if (e->refcount)
+ return -EBUSY;
+ hlist_del(&e->hlist);
+ /* Make sure the call_rcu has been executed */
+ if (e->rcu_pending)
+ rcu_barrier();
+ kfree(e);
+ return 0;
+}
+
+/*
+ * Sets the probe callback corresponding to one tracepoint.
+ */
+static void set_tracepoint(struct tracepoint_entry **entry,
+ struct tracepoint *elem, int active)
+{
+ WARN_ON(strcmp((*entry)->name, elem->name) != 0);
+
+ smp_wmb();
+ /*
+ * We also make sure that the new probe callbacks array is consistent
+ * before setting a pointer to it.
+ */
+ rcu_assign_pointer(elem->multi, (*entry)->multi);
+ elem->state = active;
+}
+
+/*
+ * Disable a tracepoint and its probe callback.
+ * Note: only waiting an RCU period after setting elem->call to the empty
+ * function insures that the original callback is not used anymore. This insured
+ * by preempt_disable around the call site.
+ */
+static void disable_tracepoint(struct tracepoint *elem)
+{
+ elem->state = 0;
+}
+
+/**
+ * tracepoint_update_probe_range - Update a probe range
+ * @begin: beginning of the range
+ * @end: end of the range
+ *
+ * Updates the probe callback corresponding to a range of tracepoints.
+ */
+void tracepoint_update_probe_range(struct tracepoint *begin,
+ struct tracepoint *end)
+{
+ struct tracepoint *iter;
+ struct tracepoint_entry *mark_entry;
+
+ mutex_lock(&tracepoints_mutex);
+ for (iter = begin; iter < end; iter++) {
+ mark_entry = get_tracepoint(iter->name);
+ if (mark_entry) {
+ set_tracepoint(&mark_entry, iter,
+ !!mark_entry->refcount);
+ } else {
+ disable_tracepoint(iter);
+ }
+ }
+ mutex_unlock(&tracepoints_mutex);
+}
+
+/*
+ * Update probes, removing the faulty probes.
+ */
+static void tracepoint_update_probes(void)
+{
+ /* Core kernel tracepoints */
+ tracepoint_update_probe_range(__start___tracepoints,
+ __stop___tracepoints);
+ /* tracepoints in modules. */
+ module_update_tracepoints();
+ /* Update immediate values */
+ core_imv_update();
+ module_imv_update();
+}
+
+/**
+ * tracepoint_probe_register - Connect a probe to a tracepoint
+ * @name: tracepoint name
+ * @probe: probe handler
+ * @probe_private: probe private data
+ *
+ * private data must be a valid allocated memory address, or NULL.
+ * Returns 0 if ok, error value on error.
+ * The probe address must at least be aligned on the architecture pointer size.
+ */
+int tracepoint_probe_register(const char *name,
+ void *probe, void *probe_private)
+{
+ struct tracepoint_entry *entry;
+ int ret = 0;
+ struct tracepoint_probe_closure *old;
+
+ mutex_lock(&tracepoints_mutex);
+ entry = get_tracepoint(name);
+ if (!entry) {
+ entry = add_tracepoint(name);
+ if (IS_ERR(entry)) {
+ ret = PTR_ERR(entry);
+ goto end;
+ }
+ }
+ /*
+ * If we detect that a call_rcu is pending for this tracepoint,
+ * make sure it's executed now.
+ */
+ if (entry->rcu_pending)
+ rcu_barrier();
+ old = tracepoint_entry_add_probe(entry, probe, probe_private);
+ if (IS_ERR(old)) {
+ ret = PTR_ERR(old);
+ goto end;
+ }
+ mutex_unlock(&tracepoints_mutex);
+ tracepoint_update_probes(); /* may update entry */
+ mutex_lock(&tracepoints_mutex);
+ entry = get_tracepoint(name);
+ WARN_ON(!entry);
+ entry->oldptr = old;
+ entry->rcu_pending = 1;
+ /* write rcu_pending before calling the RCU callback */
+ smp_wmb();
+#ifdef CONFIG_PREEMPT_RCU
+ synchronize_sched(); /* Until we have the call_rcu_sched() */
+#endif
+ call_rcu(&entry->rcu, free_old_closure);
+end:
+ mutex_unlock(&tracepoints_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tracepoint_probe_register);
+
+/**
+ * tracepoint_probe_unregister - Disconnect a probe from a tracepoint
+ * @name: tracepoint name
+ * @probe: probe function pointer
+ * @probe_private: probe private data
+ *
+ * Returns the private data given to tracepoint_probe_register, or an ERR_PTR().
+ * We do not need to call a synchronize_sched to make sure the probes have
+ * finished running before doing a module unload, because the module unload
+ * itself uses stop_machine(), which insures that every preempt disabled section
+ * have finished.
+ */
+int tracepoint_probe_unregister(const char *name,
+ void *probe, void *probe_private)
+{
+ struct tracepoint_entry *entry;
+ struct tracepoint_probe_closure *old;
+ int ret = -ENOENT;
+
+ mutex_lock(&tracepoints_mutex);
+ entry = get_tracepoint(name);
+ if (!entry)
+ goto end;
+ if (entry->rcu_pending)
+ rcu_barrier();
+ old = tracepoint_entry_remove_probe(entry, probe, probe_private);
+ mutex_unlock(&tracepoints_mutex);
+ tracepoint_update_probes(); /* may update entry */
+ mutex_lock(&tracepoints_mutex);
+ entry = get_tracepoint(name);
+ if (!entry)
+ goto end;
+ entry->oldptr = old;
+ entry->rcu_pending = 1;
+ /* write rcu_pending before calling the RCU callback */
+ smp_wmb();
+#ifdef CONFIG_PREEMPT_RCU
+ synchronize_sched(); /* Until we have the call_rcu_sched() */
+#endif
+ call_rcu(&entry->rcu, free_old_closure);
+ remove_tracepoint(name); /* Ignore busy error message */
+ ret = 0;
+end:
+ mutex_unlock(&tracepoints_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
+
+/**
+ * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
+ * @tracepoint: current tracepoints (in), next tracepoint (out)
+ * @begin: beginning of the range
+ * @end: end of the range
+ *
+ * Returns whether a next tracepoint has been found (1) or not (0).
+ * Will return the first tracepoint in the range if the input tracepoint is
+ * NULL.
+ */
+int tracepoint_get_iter_range(struct tracepoint **tracepoint,
+ struct tracepoint *begin, struct tracepoint *end)
+{
+ if (!*tracepoint && begin != end) {
+ *tracepoint = begin;
+ return 1;
+ }
+ if (*tracepoint >= begin && *tracepoint < end)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tracepoint_get_iter_range);
+
+static void tracepoint_get_iter(struct tracepoint_iter *iter)
+{
+ int found = 0;
+
+ /* Core kernel tracepoints */
+ if (!iter->module) {
+ found = tracepoint_get_iter_range(&iter->tracepoint,
+ __start___tracepoints, __stop___tracepoints);
+ if (found)
+ goto end;
+ }
+ /* tracepoints in modules. */
+ found = module_get_iter_tracepoints(iter);
+end:
+ if (!found)
+ tracepoint_iter_reset(iter);
+}
+
+void tracepoint_iter_start(struct tracepoint_iter *iter)
+{
+ tracepoint_get_iter(iter);
+}
+EXPORT_SYMBOL_GPL(tracepoint_iter_start);
+
+void tracepoint_iter_next(struct tracepoint_iter *iter)
+{
+ iter->tracepoint++;
+ /*
+ * iter->tracepoint may be invalid because we blindly incremented it.
+ * Make sure it is valid by marshalling on the tracepoints, getting the
+ * tracepoints from following modules if necessary.
+ */
+ tracepoint_get_iter(iter);
+}
+EXPORT_SYMBOL_GPL(tracepoint_iter_next);
+
+void tracepoint_iter_stop(struct tracepoint_iter *iter)
+{
+}
+EXPORT_SYMBOL_GPL(tracepoint_iter_stop);
+
+void tracepoint_iter_reset(struct tracepoint_iter *iter)
+{
+ iter->module = NULL;
+ iter->tracepoint = NULL;
+}
+EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
Index: linux-2.6-lttng/kernel/module.c
===================================================================
--- linux-2.6-lttng.orig/kernel/module.c 2008-07-03 11:49:54.000000000 -0400
+++ linux-2.6-lttng/kernel/module.c 2008-07-03 11:54:01.000000000 -0400
@@ -46,6 +46,7 @@
#include <asm/cacheflush.h>
#include <linux/license.h>
#include <asm/sections.h>
+#include <linux/tracepoint.h>
#if 0
#define DEBUGP printk
@@ -1770,6 +1771,8 @@ static struct module *load_module(void _
unsigned int unusedgplcrcindex;
unsigned int markersindex;
unsigned int markersstringsindex;
+ unsigned int tracepointsindex;
+ unsigned int tracepointsstringsindex;
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -2049,6 +2052,9 @@ static struct module *load_module(void _
markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
markersstringsindex = find_sec(hdr, sechdrs, secstrings,
"__markers_strings");
+ tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints");
+ tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings,
+ "__tracepoints_strings");
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -2076,6 +2082,12 @@ static struct module *load_module(void _
mod->num_markers =
sechdrs[markersindex].sh_size / sizeof(*mod->markers);
#endif
+#ifdef CONFIG_TRACEPOINTS
+ mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
+ mod->num_tracepoints =
+ sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
+#endif
+
/* Find duplicate symbols */
err = verify_export_symbols(mod);
@@ -2094,11 +2106,16 @@ static struct module *load_module(void _
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+ if (!(mod->taints & TAINT_FORCED_MODULE)) {
#ifdef CONFIG_MARKERS
- if (!(mod->taints & TAINT_FORCED_MODULE))
marker_update_probe_range(mod->markers,
mod->markers + mod->num_markers);
#endif
+#ifdef CONFIG_TRACEPOINTS
+ tracepoint_update_probe_range(mod->tracepoints,
+ mod->tracepoints + mod->num_tracepoints);
+#endif
+ }
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
@@ -2646,3 +2663,50 @@ void module_update_markers(void)
mutex_unlock(&module_mutex);
}
#endif
+
+#ifdef CONFIG_TRACEPOINTS
+void module_update_tracepoints(void)
+{
+ struct module *mod;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(mod, &modules, list)
+ if (!mod->taints)
+ tracepoint_update_probe_range(mod->tracepoints,
+ mod->tracepoints + mod->num_tracepoints);
+ mutex_unlock(&module_mutex);
+}
+
+/*
+ * Returns 0 if current not found.
+ * Returns 1 if current found.
+ */
+int module_get_iter_tracepoints(struct tracepoint_iter *iter)
+{
+ struct module *iter_mod;
+ int found = 0;
+
+ mutex_lock(&module_mutex);
+ list_for_each_entry(iter_mod, &modules, list) {
+ if (!iter_mod->taints) {
+ /*
+ * Sorted module list
+ */
+ if (iter_mod < iter->module)
+ continue;
+ else if (iter_mod > iter->module)
+ iter->tracepoint = NULL;
+ found = tracepoint_get_iter_range(&iter->tracepoint,
+ iter_mod->tracepoints,
+ iter_mod->tracepoints
+ + iter_mod->num_tracepoints);
+ if (found) {
+ iter->module = iter_mod;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&module_mutex);
+ return found;
+}
+#endif
Index: linux-2.6-lttng/include/linux/module.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/module.h 2008-07-03 11:47:15.000000000 -0400
+++ linux-2.6-lttng/include/linux/module.h 2008-07-03 11:49:54.000000000 -0400
@@ -16,6 +16,7 @@
#include <linux/kobject.h>
#include <linux/moduleparam.h>
#include <linux/marker.h>
+#include <linux/tracepoint.h>
#include <asm/local.h>
#include <asm/module.h>
@@ -342,6 +343,10 @@ struct module
struct marker *markers;
unsigned int num_markers;
#endif
+#ifdef CONFIG_TRACEPOINTS
+ struct tracepoint *tracepoints;
+ unsigned int num_tracepoints;
+#endif
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
@@ -450,6 +455,9 @@ extern void print_modules(void);
extern void module_update_markers(void);
+extern void module_update_tracepoints(void);
+extern int module_get_iter_tracepoints(struct tracepoint_iter *iter);
+
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -554,6 +562,15 @@ static inline void module_update_markers
{
}
+static inline void module_update_tracepoints(void)
+{
+}
+
+static inline int module_get_iter_tracepoints(struct tracepoint_iter *iter)
+{
+ return 0;
+}
+
#endif /* CONFIG_MODULES */
struct device_driver;
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC patch 2/3] LTTng tracepoint instrumentation fs
2008-07-03 16:05 [RFC patch 0/3] Tracepoints Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 1/3] Kernel Tracepoints Mathieu Desnoyers
@ 2008-07-03 16:05 ` Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 3/3] LTTng instrumentation FS tracepoint probes Mathieu Desnoyers
2 siblings, 0 replies; 6+ messages in thread
From: Mathieu Desnoyers @ 2008-07-03 16:05 UTC (permalink / raw)
To: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Masami Hiramatsu
Cc: Mathieu Desnoyers, Alexander Viro, Frank Ch. Eigler, Hideo AOKI,
Takashi Nishiie, Steven Rostedt
[-- Attachment #1: lttng-instrumentation-fs.patch --]
[-- Type: text/plain, Size: 10190 bytes --]
Core filesystem tracepoints.
Tracepoints added :
fs_buffer_wait_end
fs_buffer_wait_start
fs_close
fs_exec
fs_ioctl
fs_llseek
fs_lseek
fs_open
fs_poll
fs_pread64
fs_pwrite64
fs_read
fs_readv
fs_select
fs_write
fs_writev
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Alexander Viro <viro@zeniv.linux.org.uk>
CC: 'Peter Zijlstra' <peterz@infradead.org>
CC: "Frank Ch. Eigler" <fche@redhat.com>
CC: 'Ingo Molnar' <mingo@elte.hu>
CC: 'Hideo AOKI' <haoki@redhat.com>
CC: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
CC: 'Steven Rostedt' <rostedt@goodmis.org>
CC: Masami Hiramatsu <mhiramat@redhat.com>
---
fs/buffer.c | 3 +++
fs/compat.c | 2 ++
fs/exec.c | 2 ++
fs/fs-trace.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/ioctl.c | 3 +++
fs/open.c | 3 +++
fs/read_write.c | 19 +++++++++++++++++--
fs/select.c | 3 +++
8 files changed, 87 insertions(+), 2 deletions(-)
Index: linux-2.6-lttng/fs/buffer.c
===================================================================
--- linux-2.6-lttng.orig/fs/buffer.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/buffer.c 2008-07-03 11:59:50.000000000 -0400
@@ -41,6 +41,7 @@
#include <linux/bitops.h>
#include <linux/mpage.h>
#include <linux/bit_spinlock.h>
+#include "fs-trace.h"
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
@@ -89,7 +90,9 @@ void unlock_buffer(struct buffer_head *b
*/
void __wait_on_buffer(struct buffer_head * bh)
{
+ trace_fs_buffer_wait_start(bh);
wait_on_bit(&bh->b_state, BH_Lock, sync_buffer, TASK_UNINTERRUPTIBLE);
+ trace_fs_buffer_wait_end(bh);
}
static void
Index: linux-2.6-lttng/fs/compat.c
===================================================================
--- linux-2.6-lttng.orig/fs/compat.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/compat.c 2008-07-03 11:59:50.000000000 -0400
@@ -51,6 +51,7 @@
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/eventpoll.h>
+#include "fs-trace.h"
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -1402,6 +1403,7 @@ int compat_do_execve(char * filename,
retval = search_binary_handler(bprm, regs);
if (retval >= 0) {
+ trace_fs_exec(filename);
/* execve success */
security_bprm_free(bprm);
acct_update_integrals(current);
Index: linux-2.6-lttng/fs/ioctl.c
===================================================================
--- linux-2.6-lttng.orig/fs/ioctl.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/ioctl.c 2008-07-03 11:59:50.000000000 -0400
@@ -13,6 +13,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include "fs-trace.h"
#include <asm/ioctls.h>
@@ -201,6 +202,8 @@ asmlinkage long sys_ioctl(unsigned int f
if (!filp)
goto out;
+ trace_fs_ioctl(fd, cmd, arg);
+
error = security_file_ioctl(filp, cmd, arg);
if (error)
goto out_fput;
Index: linux-2.6-lttng/fs/open.c
===================================================================
--- linux-2.6-lttng.orig/fs/open.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/open.c 2008-07-03 11:59:50.000000000 -0400
@@ -28,6 +28,7 @@
#include <linux/rcupdate.h>
#include <linux/audit.h>
#include <linux/falloc.h>
+#include "fs-trace.h"
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
@@ -1090,6 +1091,7 @@ long do_sys_open(int dfd, const char __u
fsnotify_open(f->f_path.dentry);
fd_install(fd, f);
}
+ trace_fs_open(fd, tmp);
}
putname(tmp);
}
@@ -1179,6 +1181,7 @@ asmlinkage long sys_close(unsigned int f
filp = fdt->fd[fd];
if (!filp)
goto out_unlock;
+ trace_fs_close(fd);
rcu_assign_pointer(fdt->fd[fd], NULL);
FD_CLR(fd, fdt->close_on_exec);
__put_unused_fd(files, fd);
Index: linux-2.6-lttng/fs/read_write.c
===================================================================
--- linux-2.6-lttng.orig/fs/read_write.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/read_write.c 2008-07-03 11:59:50.000000000 -0400
@@ -16,6 +16,7 @@
#include <linux/syscalls.h>
#include <linux/pagemap.h>
#include <linux/splice.h>
+#include "fs-trace.h"
#include "read_write.h"
#include <asm/uaccess.h>
@@ -146,6 +147,9 @@ asmlinkage off_t sys_lseek(unsigned int
if (res != (loff_t)retval)
retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
}
+
+ trace_fs_lseek(fd, offset, origin);
+
fput_light(file, fput_needed);
bad:
return retval;
@@ -173,6 +177,8 @@ asmlinkage long sys_llseek(unsigned int
offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
origin);
+ trace_fs_llseek(fd, offset, origin);
+
retval = (int)offset;
if (offset >= 0) {
retval = -EFAULT;
@@ -359,6 +365,7 @@ asmlinkage ssize_t sys_read(unsigned int
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
+ trace_fs_read(fd, count);
ret = vfs_read(file, buf, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
@@ -376,6 +383,7 @@ asmlinkage ssize_t sys_write(unsigned in
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
+ trace_fs_write(fd, count);
ret = vfs_write(file, buf, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
@@ -397,8 +405,11 @@ asmlinkage ssize_t sys_pread64(unsigned
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
- if (file->f_mode & FMODE_PREAD)
+ if (file->f_mode & FMODE_PREAD) {
+ trace_fs_pread64(fd, count, pos);
ret = vfs_read(file, buf, count, &pos);
+ }
+
fput_light(file, fput_needed);
}
@@ -418,8 +429,10 @@ asmlinkage ssize_t sys_pwrite64(unsigned
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
- if (file->f_mode & FMODE_PWRITE)
+ if (file->f_mode & FMODE_PWRITE) {
+ trace_fs_pwrite64(fd, count, pos);
ret = vfs_write(file, buf, count, &pos);
+ }
fput_light(file, fput_needed);
}
@@ -663,6 +676,7 @@ sys_readv(unsigned long fd, const struct
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
+ trace_fs_readv(fd, vlen);
ret = vfs_readv(file, vec, vlen, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
@@ -684,6 +698,7 @@ sys_writev(unsigned long fd, const struc
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
+ trace_fs_writev(fd, vlen);
ret = vfs_writev(file, vec, vlen, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
Index: linux-2.6-lttng/fs/select.c
===================================================================
--- linux-2.6-lttng.orig/fs/select.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/select.c 2008-07-03 11:59:50.000000000 -0400
@@ -24,6 +24,7 @@
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/rcupdate.h>
+#include "fs-trace.h"
#include <asm/uaccess.h>
@@ -232,6 +233,7 @@ int do_select(int n, fd_set_bits *fds, s
file = fget_light(i, &fput_needed);
if (file) {
f_op = file->f_op;
+ trace_fs_select(i, *timeout);
mask = DEFAULT_POLLMASK;
if (f_op && f_op->poll)
mask = (*f_op->poll)(file, retval ? NULL : wait);
@@ -560,6 +562,7 @@ static inline unsigned int do_pollfd(str
file = fget_light(fd, &fput_needed);
mask = POLLNVAL;
if (file != NULL) {
+ trace_fs_poll(fd);
mask = DEFAULT_POLLMASK;
if (file->f_op && file->f_op->poll)
mask = file->f_op->poll(file, pwait);
Index: linux-2.6-lttng/fs/exec.c
===================================================================
--- linux-2.6-lttng.orig/fs/exec.c 2008-07-03 11:53:39.000000000 -0400
+++ linux-2.6-lttng/fs/exec.c 2008-07-03 11:59:50.000000000 -0400
@@ -51,6 +51,7 @@
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
+#include "fs-trace.h"
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -1330,6 +1331,7 @@ int do_execve(char * filename,
retval = search_binary_handler(bprm,regs);
if (retval >= 0) {
+ trace_fs_exec(filename);
/* execve success */
security_bprm_free(bprm);
acct_update_integrals(current);
Index: linux-2.6-lttng/fs/fs-trace.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/fs/fs-trace.h 2008-07-03 11:59:50.000000000 -0400
@@ -0,0 +1,54 @@
+#ifndef _FS_TRACE_H
+#define _FS_TRACE_H
+
+#include <linux/tracepoint.h>
+
+DEFINE_TRACE(fs_buffer_wait_start,
+ TPPROTO(struct buffer_head *bh),
+ TPARGS(bh));
+DEFINE_TRACE(fs_buffer_wait_end,
+ TPPROTO(struct buffer_head *bh),
+ TPARGS(bh));
+DEFINE_TRACE(fs_exec,
+ TPPROTO(char *filename),
+ TPARGS(filename));
+DEFINE_TRACE(fs_ioctl,
+ TPPROTO(unsigned int fd, unsigned int cmd, unsigned long arg),
+ TPARGS(fd, cmd, arg));
+DEFINE_TRACE(fs_open,
+ TPPROTO(unsigned int fd, char *filename),
+ TPARGS(fd, filename));
+DEFINE_TRACE(fs_close,
+ TPPROTO(unsigned int fd),
+ TPARGS(fd));
+DEFINE_TRACE(fs_lseek,
+ TPPROTO(unsigned int fd, unsigned long offset, unsigned int origin),
+ TPARGS(fd, offset, origin));
+DEFINE_TRACE(fs_llseek,
+ TPPROTO(unsigned int fd, loff_t offset, unsigned int origin),
+ TPARGS(fd, offset, origin));
+DEFINE_TRACE(fs_read,
+ TPPROTO(unsigned int fd, size_t count),
+ TPARGS(fd, count));
+DEFINE_TRACE(fs_write,
+ TPPROTO(unsigned int fd, size_t count),
+ TPARGS(fd, count));
+DEFINE_TRACE(fs_pread64,
+ TPPROTO(unsigned int fd, size_t count, loff_t pos),
+ TPARGS(fd, count, pos));
+DEFINE_TRACE(fs_pwrite64,
+ TPPROTO(unsigned int fd, size_t count, loff_t pos),
+ TPARGS(fd, count, pos));
+DEFINE_TRACE(fs_readv,
+ TPPROTO(unsigned long fd, unsigned long vlen),
+ TPARGS(fd, vlen));
+DEFINE_TRACE(fs_writev,
+ TPPROTO(unsigned long fd, unsigned long vlen),
+ TPARGS(fd, vlen));
+DEFINE_TRACE(fs_select,
+ TPPROTO(int fd, s64 timeout),
+ TPARGS(fd, timeout));
+DEFINE_TRACE(fs_poll,
+ TPPROTO(int fd),
+ TPARGS(fd));
+#endif
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC patch 3/3] LTTng instrumentation FS tracepoint probes
2008-07-03 16:05 [RFC patch 0/3] Tracepoints Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 1/3] Kernel Tracepoints Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 2/3] LTTng tracepoint instrumentation fs Mathieu Desnoyers
@ 2008-07-03 16:05 ` Mathieu Desnoyers
2 siblings, 0 replies; 6+ messages in thread
From: Mathieu Desnoyers @ 2008-07-03 16:05 UTC (permalink / raw)
To: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Masami Hiramatsu
Cc: Mathieu Desnoyers, Alexander Viro, Frank Ch. Eigler, Hideo AOKI,
Takashi Nishiie, Steven Rostedt
[-- Attachment #1: lttng-instrumentation-fs-tracepoints-probes.patch --]
[-- Type: text/plain, Size: 6465 bytes --]
Create a module which declares FS tracepoint probes, using markers.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
CC: Alexander Viro <viro@zeniv.linux.org.uk>
CC: 'Peter Zijlstra' <peterz@infradead.org>
CC: "Frank Ch. Eigler" <fche@redhat.com>
CC: 'Ingo Molnar' <mingo@elte.hu>
CC: 'Hideo AOKI' <haoki@redhat.com>
CC: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
CC: 'Steven Rostedt' <rostedt@goodmis.org>
CC: Masami Hiramatsu <mhiramat@redhat.com>
---
fs/Makefile | 1
fs/fs-trace.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 173 insertions(+)
Index: linux-2.6-lttng/fs/fs-trace.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6-lttng/fs/fs-trace.c 2008-07-03 11:53:11.000000000 -0400
@@ -0,0 +1,172 @@
+/*
+ * fs/fs-trace.c
+ *
+ * FS tracepoint probes.
+ */
+
+#include <linux/module.h>
+#include <linux/buffer_head.h>
+#include "fs-trace.h"
+
+static void probe_fs_buffer_wait_start(void *private_data,
+ struct buffer_head *bh)
+{
+ trace_mark(fs_buffer_wait_start, "bh %p", bh);
+}
+
+static void probe_fs_buffer_wait_end(void *private_data,
+ struct buffer_head *bh)
+{
+ trace_mark(fs_buffer_wait_end, "bh %p", bh);
+}
+
+static void probe_fs_exec(void *private_data, char *filename)
+{
+ trace_mark(fs_exec, "filename %s", filename);
+}
+
+static void probe_fs_ioctl(void *private_data,
+ unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ trace_mark(fs_ioctl, "fd %u cmd %u arg %lu", fd, cmd, arg);
+}
+
+static void probe_fs_open(void *private_data, unsigned int fd, char *filename)
+{
+ trace_mark(fs_open, "fd %d filename %s", fd, filename);
+}
+
+static void probe_fs_close(void *private_data, unsigned int fd)
+{
+ trace_mark(fs_close, "fd %u", fd);
+}
+
+static void probe_fs_lseek(void *private_data,
+ unsigned int fd, unsigned long offset, unsigned int origin)
+{
+ trace_mark(fs_lseek, "fd %u offset %ld origin %u", fd, offset, origin);
+}
+
+static void probe_fs_llseek(void *private_data,
+ unsigned int fd, loff_t offset, unsigned int origin)
+{
+ trace_mark(fs_llseek, "fd %u offset %llu origin %u", fd,
+ (unsigned long long)offset, origin);
+}
+
+static void probe_fs_read(void *private_data, unsigned int fd, size_t count)
+{
+ trace_mark(fs_read, "fd %u count %zu", fd, count);
+}
+
+static void probe_fs_write(void *private_datat, unsigned int fd, size_t count)
+{
+ trace_mark(fs_write, "fd %u count %zu", fd, count);
+}
+
+static void probe_fs_pread64(void *private_data,
+ unsigned int fd, size_t count, loff_t pos)
+{
+ trace_mark(fs_pread64, "fd %u count %zu pos %llu",
+ fd, count, (unsigned long long)pos);
+}
+
+static void probe_fs_pwrite64(void *private_data,
+ unsigned int fd, size_t count, loff_t pos)
+{
+ trace_mark(fs_pwrite64, "fd %u count %zu pos %llu",
+ fd, count, (unsigned long long)pos);
+}
+
+static void probe_fs_readv(void *private_data,
+ unsigned long fd, unsigned long vlen)
+{
+ trace_mark(fs_readv, "fd %lu vlen %lu", fd, vlen);
+}
+
+static void probe_fs_writev(void *private_data,
+ unsigned long fd, unsigned long vlen)
+{
+ trace_mark(fs_writev, "fd %lu vlen %lu", fd, vlen);
+}
+
+static void probe_fs_select(void *private_data, int fd, s64 timeout)
+{
+ trace_mark(fs_select, "fd %d timeout #8d%lld", fd, (long long)timeout);
+}
+
+static void probe_fs_poll(void *private_data, int fd)
+{
+ trace_mark(fs_pollfd, "fd %d", fd);
+}
+
+
+int __init fs_trace_init(void)
+{
+ int ret;
+
+ ret = register_trace_fs_buffer_wait_start(probe_fs_buffer_wait_start,
+ NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_buffer_wait_end(probe_fs_buffer_wait_end,
+ NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_exec(probe_fs_exec, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_ioctl(probe_fs_ioctl, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_open(probe_fs_open, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_close(probe_fs_close, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_lseek(probe_fs_lseek, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_llseek(probe_fs_llseek, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_read(probe_fs_read, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_write(probe_fs_write, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_pread64(probe_fs_pread64, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_pwrite64(probe_fs_pwrite64, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_readv(probe_fs_readv, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_writev(probe_fs_writev, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_select(probe_fs_select, NULL);
+ WARN_ON(ret);
+ ret = register_trace_fs_poll(probe_fs_poll, NULL);
+ WARN_ON(ret);
+
+ return 0;
+}
+
+module_init(fs_trace_init);
+
+void __exit fs_trace_exit(void)
+{
+ unregister_trace_fs_poll(probe_fs_poll, NULL);
+ unregister_trace_fs_select(probe_fs_select, NULL);
+ unregister_trace_fs_writev(probe_fs_writev, NULL);
+ unregister_trace_fs_readv(probe_fs_readv, NULL);
+ unregister_trace_fs_pwrite64(probe_fs_pwrite64, NULL);
+ unregister_trace_fs_pread64(probe_fs_pread64, NULL);
+ unregister_trace_fs_write(probe_fs_write, NULL);
+ unregister_trace_fs_read(probe_fs_read, NULL);
+ unregister_trace_fs_llseek(probe_fs_llseek, NULL);
+ unregister_trace_fs_lseek(probe_fs_lseek, NULL);
+ unregister_trace_fs_close(probe_fs_close, NULL);
+ unregister_trace_fs_open(probe_fs_open, NULL);
+ unregister_trace_fs_ioctl(probe_fs_ioctl, NULL);
+ unregister_trace_fs_exec(probe_fs_exec, NULL);
+ unregister_trace_fs_buffer_wait_end(probe_fs_buffer_wait_end, NULL);
+ unregister_trace_fs_buffer_wait_start(probe_fs_buffer_wait_start, NULL);
+}
+
+module_exit(fs_trace_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("FS Tracepoint Probes");
Index: linux-2.6-lttng/fs/Makefile
===================================================================
--- linux-2.6-lttng.orig/fs/Makefile 2008-07-03 11:47:14.000000000 -0400
+++ linux-2.6-lttng/fs/Makefile 2008-07-03 11:49:54.000000000 -0400
@@ -63,6 +63,7 @@ obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
+obj-$(CONFIG_TRACEPROBES) += fs-trace.o
obj-$(CONFIG_DLM) += dlm/
# Do not add any filesystems before this line
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC patch 1/3] Kernel Tracepoints
2008-07-03 16:05 ` [RFC patch 1/3] Kernel Tracepoints Mathieu Desnoyers
@ 2008-07-03 21:47 ` Masami Hiramatsu
2008-07-04 13:57 ` Mathieu Desnoyers
0 siblings, 1 reply; 6+ messages in thread
From: Masami Hiramatsu @ 2008-07-03 21:47 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Frank Ch. Eigler,
Hideo AOKI, Takashi Nishiie, Steven Rostedt, Alexander Viro
Hi Mathieu,
I couldn't apply this patch against 2.6.26-rc8, and have
some trivial comments.
Mathieu Desnoyers wrote:
> Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
>
> Allows complete typing verification. No format string required.
>
> TODO : Documentation/tracepoint.txt
>
> Changelog :
> - Use #name ":" #proto as string to identify the tracepoint in the
> tracepoint table. This will make sure not type mismatch happens due to
> connexion of a probe with the wrong type to a tracepoint declared with
> the same name in a different header.
>
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
> CC: 'Peter Zijlstra' <peterz@infradead.org>
> CC: "Frank Ch. Eigler" <fche@redhat.com>
> CC: 'Ingo Molnar' <mingo@elte.hu>
> CC: 'Hideo AOKI' <haoki@redhat.com>
> CC: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
> CC: 'Steven Rostedt' <rostedt@goodmis.org>
> CC: Alexander Viro <viro@zeniv.linux.org.uk>
> ---
> include/asm-generic/vmlinux.lds.h | 6
> include/linux/module.h | 17 +
> include/linux/tracepoint.h | 139 ++++++++++
> init/Kconfig | 16 +
> kernel/Makefile | 1
> kernel/module.c | 66 ++++-
> kernel/tracepoint.c | 498 ++++++++++++++++++++++++++++++++++++++
> 7 files changed, 741 insertions(+), 2 deletions(-)
>
> Index: linux-2.6-lttng/init/Kconfig
> ===================================================================
> --- linux-2.6-lttng.orig/init/Kconfig 2008-07-03 11:47:15.000000000 -0400
> +++ linux-2.6-lttng/init/Kconfig 2008-07-03 11:49:54.000000000 -0400
> @@ -782,12 +782,28 @@ config PROFILING
> Say Y here to enable the extended profiling support mechanisms used
> by profilers such as OProfile.
>
> +config TRACEPOINTS
> + bool "Activate tracepoints"
> + default y
> + help
> + Place an empty function call at each tracepoint site. Can be
> + dynamically changed for a probe function.
> +
> config MARKERS
> bool "Activate markers"
> help
> Place an empty function call at each marker site. Can be
> dynamically changed for a probe function.
>
> +config TRACEPROBES
> + tristate "Compile generic tracing probes"
> + depends on MARKERS
> + default y
> + help
> + Compile generic tracing probes, which connect to the tracepoints when
> + loaded and format the information collected by the tracepoints with
> + the Markers.
> +
> source "arch/Kconfig"
might this part better go to PATCH 3/3?
[...]
> +
> +
> +#define TPPROTO(args...) args
> +#define TPARGS(args...) args
> +
> +#ifdef CONFIG_TRACEPOINTS
> +
> +/*
> + * Note : the empty asm volatile with read constraint is used here instead of a
> + * "used" attribute to fix a gcc 4.1.x bug.
There seems no empty asm...
> + * Make sure the alignment of the structure in the __tracepoints 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 DEFINE_TRACE(name, proto, args) \
> + static inline void _do_trace_##name(struct tracepoint *tp, proto) \
> + { \
> + int i; \
> + struct tracepoint_probe_closure *multi; \
> + preempt_disable(); \
> + multi = tp->multi; \
> + smp_read_barrier_depends(); \
> + if (multi) { \
> + for (i = 0; multi[i].func; i++) { \
> + ((void(*)(void *private_data, proto)) \
> + (multi[i].func))(multi[i].probe_private, args);\
> + } \
> + } \
> + preempt_enable(); \
> + } \
> + static inline void trace_##name(proto) \
> + { \
> + static const char __tpstrtab_##name[] \
> + __attribute__((section("__tracepoints_strings"))) \
> + = #name ":" #proto; \
> + static struct tracepoint __tracepoint_##name \
> + __attribute__((section("__tracepoints"), aligned(8))) = \
> + { __tpstrtab_##name, 0, NULL }; \
> + if (unlikely(__tracepoint_##name.state)) \
> + _do_trace_##name(&__tracepoint_##name, args); \
> + } \
> + static inline int register_trace_##name( \
> + void (*probe)(void *private_data, proto), \
> + void *private_data) \
> + { \
> + return tracepoint_probe_register(#name ":" #proto, \
> + (void *)probe, private_data); \
> + } \
> + static inline void unregister_trace_##name( \
> + void (*probe)(void *private_data, proto), \
> + void *private_data) \
> + { \
> + tracepoint_probe_unregister(#name ":" #proto, \
> + (void *)probe, private_data); \
> + }
> +
As we are discussing on another thread, this macro can't handle
non-argument tracepoint.
[...]
> Index: linux-2.6-lttng/kernel/tracepoint.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6-lttng/kernel/tracepoint.c 2008-07-03 11:54:30.000000000 -0400
> @@ -0,0 +1,498 @@
> +/*
> + * Copyright (C) 2007 Mathieu Desnoyers
trivial: it should be 2008? :-)
[...]
> Index: linux-2.6-lttng/kernel/module.c
> ===================================================================
> --- linux-2.6-lttng.orig/kernel/module.c 2008-07-03 11:49:54.000000000 -0400
> +++ linux-2.6-lttng/kernel/module.c 2008-07-03 11:54:01.000000000 -0400
> @@ -46,6 +46,7 @@
> #include <asm/cacheflush.h>
> #include <linux/license.h>
> #include <asm/sections.h>
> +#include <linux/tracepoint.h>
>
> #if 0
> #define DEBUGP printk
> @@ -1770,6 +1771,8 @@ static struct module *load_module(void _
> unsigned int unusedgplcrcindex;
> unsigned int markersindex;
> unsigned int markersstringsindex;
> + unsigned int tracepointsindex;
> + unsigned int tracepointsstringsindex;
> struct module *mod;
> long err = 0;
> void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
> @@ -2049,6 +2052,9 @@ static struct module *load_module(void _
> markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
> markersstringsindex = find_sec(hdr, sechdrs, secstrings,
> "__markers_strings");
> + tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints");
> + tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings,
> + "__tracepoints_strings");
>
> /* Now do relocations. */
> for (i = 1; i < hdr->e_shnum; i++) {
> @@ -2076,6 +2082,12 @@ static struct module *load_module(void _
> mod->num_markers =
> sechdrs[markersindex].sh_size / sizeof(*mod->markers);
> #endif
> +#ifdef CONFIG_TRACEPOINTS
> + mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
> + mod->num_tracepoints =
> + sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
> +#endif
> +
>
> /* Find duplicate symbols */
> err = verify_export_symbols(mod);
> @@ -2094,11 +2106,16 @@ static struct module *load_module(void _
>
> add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
>
> + if (!(mod->taints & TAINT_FORCED_MODULE)) {
> #ifdef CONFIG_MARKERS
> - if (!(mod->taints & TAINT_FORCED_MODULE))
> marker_update_probe_range(mod->markers,
> mod->markers + mod->num_markers);
Here, this hunk was rejected, because "Markers Support for
Proprierary Modules" patch doesn't merged yet.
> #endif
> +#ifdef CONFIG_TRACEPOINTS
> + tracepoint_update_probe_range(mod->tracepoints,
> + mod->tracepoints + mod->num_tracepoints);
> +#endif
> + }
> err = module_finalize(hdr, sechdrs, mod);
> if (err < 0)
> goto cleanup;
Thank you,
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division
e-mail: mhiramat@redhat.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC patch 1/3] Kernel Tracepoints
2008-07-03 21:47 ` Masami Hiramatsu
@ 2008-07-04 13:57 ` Mathieu Desnoyers
0 siblings, 0 replies; 6+ messages in thread
From: Mathieu Desnoyers @ 2008-07-04 13:57 UTC (permalink / raw)
To: Masami Hiramatsu
Cc: akpm, Ingo Molnar, linux-kernel, Peter Zijlstra, Frank Ch. Eigler,
Hideo AOKI, Takashi Nishiie, Steven Rostedt, Alexander Viro
* Masami Hiramatsu (mhiramat@redhat.com) wrote:
> Hi Mathieu,
>
> I couldn't apply this patch against 2.6.26-rc8, and have
> some trivial comments.
>
> Mathieu Desnoyers wrote:
> > Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
> >
> > Allows complete typing verification. No format string required.
> >
> > TODO : Documentation/tracepoint.txt
> >
> > Changelog :
> > - Use #name ":" #proto as string to identify the tracepoint in the
> > tracepoint table. This will make sure not type mismatch happens due to
> > connexion of a probe with the wrong type to a tracepoint declared with
> > the same name in a different header.
> >
> > Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
> > CC: 'Peter Zijlstra' <peterz@infradead.org>
> > CC: "Frank Ch. Eigler" <fche@redhat.com>
> > CC: 'Ingo Molnar' <mingo@elte.hu>
> > CC: 'Hideo AOKI' <haoki@redhat.com>
> > CC: Takashi Nishiie <t-nishiie@np.css.fujitsu.com>
> > CC: 'Steven Rostedt' <rostedt@goodmis.org>
> > CC: Alexander Viro <viro@zeniv.linux.org.uk>
> > ---
> > include/asm-generic/vmlinux.lds.h | 6
> > include/linux/module.h | 17 +
> > include/linux/tracepoint.h | 139 ++++++++++
> > init/Kconfig | 16 +
> > kernel/Makefile | 1
> > kernel/module.c | 66 ++++-
> > kernel/tracepoint.c | 498 ++++++++++++++++++++++++++++++++++++++
> > 7 files changed, 741 insertions(+), 2 deletions(-)
> >
> > Index: linux-2.6-lttng/init/Kconfig
> > ===================================================================
> > --- linux-2.6-lttng.orig/init/Kconfig 2008-07-03 11:47:15.000000000 -0400
> > +++ linux-2.6-lttng/init/Kconfig 2008-07-03 11:49:54.000000000 -0400
> > @@ -782,12 +782,28 @@ config PROFILING
> > Say Y here to enable the extended profiling support mechanisms used
> > by profilers such as OProfile.
> >
> > +config TRACEPOINTS
> > + bool "Activate tracepoints"
> > + default y
> > + help
> > + Place an empty function call at each tracepoint site. Can be
> > + dynamically changed for a probe function.
> > +
> > config MARKERS
> > bool "Activate markers"
> > help
> > Place an empty function call at each marker site. Can be
> > dynamically changed for a probe function.
> >
> > +config TRACEPROBES
> > + tristate "Compile generic tracing probes"
> > + depends on MARKERS
> > + default y
> > + help
> > + Compile generic tracing probes, which connect to the tracepoints when
> > + loaded and format the information collected by the tracepoints with
> > + the Markers.
> > +
> > source "arch/Kconfig"
>
> might this part better go to PATCH 3/3?
>
Will fix.
> [...]
> > +
> > +
> > +#define TPPROTO(args...) args
> > +#define TPARGS(args...) args
> > +
> > +#ifdef CONFIG_TRACEPOINTS
> > +
> > +/*
> > + * Note : the empty asm volatile with read constraint is used here instead of a
> > + * "used" attribute to fix a gcc 4.1.x bug.
>
> There seems no empty asm...
>
True, should be removed from markers too.
> > + * Make sure the alignment of the structure in the __tracepoints 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 DEFINE_TRACE(name, proto, args) \
> > + static inline void _do_trace_##name(struct tracepoint *tp, proto) \
> > + { \
> > + int i; \
> > + struct tracepoint_probe_closure *multi; \
> > + preempt_disable(); \
> > + multi = tp->multi; \
> > + smp_read_barrier_depends(); \
> > + if (multi) { \
> > + for (i = 0; multi[i].func; i++) { \
> > + ((void(*)(void *private_data, proto)) \
> > + (multi[i].func))(multi[i].probe_private, args);\
> > + } \
> > + } \
> > + preempt_enable(); \
> > + } \
> > + static inline void trace_##name(proto) \
> > + { \
> > + static const char __tpstrtab_##name[] \
> > + __attribute__((section("__tracepoints_strings"))) \
> > + = #name ":" #proto; \
> > + static struct tracepoint __tracepoint_##name \
> > + __attribute__((section("__tracepoints"), aligned(8))) = \
> > + { __tpstrtab_##name, 0, NULL }; \
> > + if (unlikely(__tracepoint_##name.state)) \
> > + _do_trace_##name(&__tracepoint_##name, args); \
> > + } \
> > + static inline int register_trace_##name( \
> > + void (*probe)(void *private_data, proto), \
> > + void *private_data) \
> > + { \
> > + return tracepoint_probe_register(#name ":" #proto, \
> > + (void *)probe, private_data); \
> > + } \
> > + static inline void unregister_trace_##name( \
> > + void (*probe)(void *private_data, proto), \
> > + void *private_data) \
> > + { \
> > + tracepoint_probe_unregister(#name ":" #proto, \
> > + (void *)probe, private_data); \
> > + }
> > +
>
> As we are discussing on another thread, this macro can't handle
> non-argument tracepoint.
>
Will fix.
> [...]
> > Index: linux-2.6-lttng/kernel/tracepoint.c
> > ===================================================================
> > --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> > +++ linux-2.6-lttng/kernel/tracepoint.c 2008-07-03 11:54:30.000000000 -0400
> > @@ -0,0 +1,498 @@
> > +/*
> > + * Copyright (C) 2007 Mathieu Desnoyers
>
> trivial: it should be 2008? :-)
>
I always have difficulty remembering the day of the week. Now years... :)
> [...]
> > Index: linux-2.6-lttng/kernel/module.c
> > ===================================================================
> > --- linux-2.6-lttng.orig/kernel/module.c 2008-07-03 11:49:54.000000000 -0400
> > +++ linux-2.6-lttng/kernel/module.c 2008-07-03 11:54:01.000000000 -0400
> > @@ -46,6 +46,7 @@
> > #include <asm/cacheflush.h>
> > #include <linux/license.h>
> > #include <asm/sections.h>
> > +#include <linux/tracepoint.h>
> >
> > #if 0
> > #define DEBUGP printk
> > @@ -1770,6 +1771,8 @@ static struct module *load_module(void _
> > unsigned int unusedgplcrcindex;
> > unsigned int markersindex;
> > unsigned int markersstringsindex;
> > + unsigned int tracepointsindex;
> > + unsigned int tracepointsstringsindex;
> > struct module *mod;
> > long err = 0;
> > void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
> > @@ -2049,6 +2052,9 @@ static struct module *load_module(void _
> > markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
> > markersstringsindex = find_sec(hdr, sechdrs, secstrings,
> > "__markers_strings");
> > + tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints");
> > + tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings,
> > + "__tracepoints_strings");
> >
> > /* Now do relocations. */
> > for (i = 1; i < hdr->e_shnum; i++) {
> > @@ -2076,6 +2082,12 @@ static struct module *load_module(void _
> > mod->num_markers =
> > sechdrs[markersindex].sh_size / sizeof(*mod->markers);
> > #endif
> > +#ifdef CONFIG_TRACEPOINTS
> > + mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
> > + mod->num_tracepoints =
> > + sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
> > +#endif
> > +
> >
> > /* Find duplicate symbols */
> > err = verify_export_symbols(mod);
> > @@ -2094,11 +2106,16 @@ static struct module *load_module(void _
> >
> > add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
> >
> > + if (!(mod->taints & TAINT_FORCED_MODULE)) {
> > #ifdef CONFIG_MARKERS
> > - if (!(mod->taints & TAINT_FORCED_MODULE))
> > marker_update_probe_range(mod->markers,
> > mod->markers + mod->num_markers);
>
> Here, this hunk was rejected, because "Markers Support for
> Proprierary Modules" patch doesn't merged yet.
>
Ok, I'll change the patch order.
> > #endif
> > +#ifdef CONFIG_TRACEPOINTS
> > + tracepoint_update_probe_range(mod->tracepoints,
> > + mod->tracepoints + mod->num_tracepoints);
> > +#endif
> > + }
> > err = module_finalize(hdr, sechdrs, mod);
> > if (err < 0)
> > goto cleanup;
>
> Thank you,
>
Thanks for the review,
Mathieu
> --
> Masami Hiramatsu
>
> Software Engineer
> Hitachi Computer Products (America) Inc.
> Software Solutions Division
>
> e-mail: mhiramat@redhat.com
>
--
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-07-04 13:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-03 16:05 [RFC patch 0/3] Tracepoints Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 1/3] Kernel Tracepoints Mathieu Desnoyers
2008-07-03 21:47 ` Masami Hiramatsu
2008-07-04 13:57 ` Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 2/3] LTTng tracepoint instrumentation fs Mathieu Desnoyers
2008-07-03 16:05 ` [RFC patch 3/3] LTTng instrumentation FS tracepoint probes Mathieu Desnoyers
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.