[Kernelpatches-commits] wjhuang commits r7 - trunk/wjhuang/marker_patches
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Jul 3 19:22:00 PDT 2008
Author: wjhuang
Date: 2008-07-03 19:22:00 -0700 (Thu, 03 Jul 2008)
New Revision: 7
Removed:
trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5.patch
trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5u1.patch
trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u4.patch
trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u5.patch
trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u6.patch
Log:
remove the test files
Deleted: trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5.patch
===================================================================
--- trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5.patch 2008-07-04 02:18:23 UTC (rev 6)
+++ trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5.patch 2008-07-04 02:22:00 UTC (rev 7)
@@ -1,1882 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 7682056..d1b7d78 100644
---- a/Makefile
-+++ b/Makefile
-@@ -601,7 +601,7 @@ quiet_cmd_vmlinux__ ?= LD $@
- cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
- --start-group $(vmlinux-main) --end-group \
-- $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
-+ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
-
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN .version
-@@ -725,11 +725,30 @@ debug_kallsyms: .tmp_map$(last_kallsyms)
-
- endif # ifdef CONFIG_KALLSYMS
-
-+# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
-+# relevant sections renamed as per the linker script.
-+quiet_cmd_vmlinux-modpost = LD $@
-+ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
-+ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
-+ $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
-+define rule_vmlinux-modpost
-+ :
-+ +$(call cmd,vmlinux-modpost)
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
-+ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
-+endef
-+
- # vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
-+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
-+ $(call vmlinux-modpost)
- $(call if_changed_rule,vmlinux__)
- $(Q)rm -f .old_version
-
-+# build vmlinux.o first to catch section mismatch errors early
-+$(kallsyms.o): vmlinux.o
-+vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
-+ $(call if_changed_rule,vmlinux-modpost)
-+
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
-index 7dec8f0..73f833c 100644
---- a/arch/i386/Kconfig
-+++ b/arch/i386/Kconfig
-@@ -1205,6 +1205,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/i386/Kconfig.debug"
-diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
-index a44d95d..23d73bb 100644
---- a/arch/i386/kernel/vmlinux.lds.S
-+++ b/arch/i386/kernel/vmlinux.lds.S
-@@ -61,6 +61,7 @@ SECTIONS
- /* writeable */
- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- } :data
-
-diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index c45b7b5..aee46db 100644
---- a/arch/ia64/Kconfig
-+++ b/arch/ia64/Kconfig
-@@ -587,6 +587,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/ia64/Kconfig.debug"
-diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
-index 5b0d5f6..9c63f83 100644
---- a/arch/ia64/kernel/vmlinux.lds.S
-+++ b/arch/ia64/kernel/vmlinux.lds.S
-@@ -206,7 +206,7 @@ SECTIONS
-
- data : { } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET)
-- { *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
-+ { *(.data) *(.data1) *(.gnu.linkonce.d*) MARKER CONSTRUCTORS }
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET)
-diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 41024aa..4ab8d59 100644
---- a/arch/powerpc/Kconfig
-+++ b/arch/powerpc/Kconfig
-@@ -1095,6 +1095,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/powerpc/Kconfig.debug"
-diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
-index c02298a..709bc47 100644
---- a/arch/powerpc/kernel/vmlinux.lds.S
-+++ b/arch/powerpc/kernel/vmlinux.lds.S
-@@ -176,11 +176,13 @@ SECTIONS
- *(.data)
- *(.sdata)
- *(.got.plt) *(.got)
-+ MARKER
- }
- #else
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
-+ MARKER
- }
-
- .opd : {
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 974474a..c81600c 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -505,6 +505,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/s390/Kconfig.debug"
-diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
-index df0c16a..69826b1 100644
---- a/arch/s390/kernel/vmlinux.lds.S
-+++ b/arch/s390/kernel/vmlinux.lds.S
-@@ -46,6 +46,7 @@ SECTIONS
-
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
-index b627f8d..e0467d1 100644
---- a/arch/sparc64/Kconfig
-+++ b/arch/sparc64/Kconfig
-@@ -427,6 +427,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/sparc64/Kconfig.debug"
-diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
-index b097379..1f10e43 100644
---- a/arch/sparc64/kernel/vmlinux.lds.S
-+++ b/arch/sparc64/kernel/vmlinux.lds.S
-@@ -27,6 +27,7 @@ SECTIONS
- .data :
- {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
-diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
-index d284a9a..e556e06 100644
---- a/arch/x86_64/Kconfig
-+++ b/arch/x86_64/Kconfig
-@@ -704,6 +704,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/x86_64/Kconfig.debug"
-diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
-index f17185f..a33251a 100644
---- a/arch/x86_64/kernel/vmlinux.lds.S
-+++ b/arch/x86_64/kernel/vmlinux.lds.S
-@@ -67,6 +67,7 @@ SECTIONS
- /* Data */
- .data : AT(ADDR(.data) - LOAD_OFFSET) {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- } :data
-
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 6a40707..9b0fab5 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -125,7 +125,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
- // ================= 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);
-@@ -138,8 +138,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast);
- 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);
-
-
- /////////////////////////////////////////////////////////////////////////////////
-@@ -903,12 +903,13 @@ static int ad_lacpdu_send(struct port *port)
- * 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);
-@@ -923,7 +924,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
- skb->nh.raw = skb->data + 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
-@@ -1723,7 +1724,7 @@ static void ad_disable_collecting_distributing(struct port *port)
- */
- 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
-@@ -1756,13 +1757,14 @@ static void ad_marker_info_send(struct port *port)
- * @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
-@@ -1781,7 +1783,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
- * 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
-@@ -2179,15 +2182,16 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
- 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:
-diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
-index 6ad5ad6..bf93e7e 100644
---- a/drivers/net/bonding/bond_3ad.h
-+++ b/drivers/net/bonding/bond_3ad.h
-@@ -92,7 +92,8 @@ 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 +149,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 +162,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()
-
-diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
-index 5102c6b..aed4049 100644
---- a/drivers/scsi/qla4xxx/ql4_fw.h
-+++ b/drivers/scsi/qla4xxx/ql4_fw.h
-@@ -744,7 +744,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 */
-diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
-index 4e532b4..43860eb 100644
---- a/drivers/scsi/qla4xxx/ql4_iocb.c
-+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
-@@ -65,7 +65,8 @@ int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
- 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;
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index b9e964c..a175f1e 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -9,12 +9,21 @@
- /* Align . to a 8 byte boundary equals to maximum function alignment. */
- #define ALIGN_FUNCTION() . = ALIGN(8)
-
-+/* Kernel markers : pointers */
-+#define MARKER \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__start___markers) = .; \
-+ *(__markers) \
-+ VMLINUX_SYMBOL(__stop___markers) = .;
-+
-+
- #define RODATA \
- . = ALIGN(4096); \
- .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_rodata) = .; \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
-+ *(__markers_strings) /* Markers: strings */ \
- } \
- \
- .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
-diff --git a/include/linux/marker.h b/include/linux/marker.h
-new file mode 100644
-index 0000000..efbc82b
---- /dev/null
-+++ b/include/linux/marker.h
-@@ -0,0 +1,139 @@
-+#ifndef _LINUX_MARKER_H
-+#define _LINUX_MARKER_H
-+
-+/*
-+ * Code markup for dynamic and static tracing.
-+ *
-+ * See Documentation/marker.txt.
-+ *
-+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
-+ *
-+ * This file is released under the GPLv2.
-+ * See the file COPYING for more details.
-+ */
-+
-+#include <linux/types.h>
-+
-+struct module;
-+struct marker;
-+
-+/**
-+ * marker_probe_func - Type of a marker probe function
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @fmt: format string
-+ * @args: variable argument list pointer. Use a pointer to overcome C's
-+ * inability to pass this around as a pointer in a portable manner in
-+ * the callee otherwise.
-+ *
-+ * 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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args);
-+
-+struct marker_probe_closure {
-+ marker_probe_func *func; /* Callback */
-+ void *probe_private; /* Private probe data */
-+};
-+
-+struct marker {
-+ const char *name; /* Marker name */
-+ const char *format; /* Marker format string, describing the
-+ * variable argument list.
-+ */
-+ char state; /* Marker state. */
-+ char ptype; /* probe type : 0 : single, 1 : multi */
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+} __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_private, format, args...) \
-+ do { \
-+ static const char __mstrtab_##name[] \
-+ __attribute__((section("__markers_strings"))) \
-+ = #name "\0" format; \
-+ static struct marker __mark_##name \
-+ __attribute__((section("__markers"), aligned(8))) = \
-+ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
-+ 0, 0, marker_probe_cb, \
-+ { __mark_empty_function, NULL}, NULL }; \
-+ __mark_check_format(format, ## args); \
-+ if (unlikely(__mark_##name.state)) { \
-+ (*__mark_##name.call) \
-+ (&__mark_##name, call_private, \
-+ format, ## args); \
-+ } \
-+ } while (0)
-+
-+extern void marker_update_probe_range(struct marker *begin,
-+ struct marker *end);
-+#else /* !CONFIG_MARKERS */
-+#define __trace_mark(name, call_private, format, args...) \
-+ __mark_check_format(format, ## args)
-+static inline void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{ }
-+#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)
-+
-+/**
-+ * 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 __attribute__ ((format (printf, 1, 2))) __mark_check_format(const char *fmt, ...)
-+{
-+}
-+
-+extern marker_probe_func __mark_empty_function;
-+
-+extern void marker_probe_cb(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+extern void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+
-+/*
-+ * 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 *probe_private);
-+
-+/*
-+ * Returns the private data given to marker_probe_register.
-+ */
-+extern int marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private);
-+/*
-+ * Unregister a marker by providing the registered private data.
-+ */
-+extern int marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private);
-+
-+extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
-+ int num);
-+
-+#endif
-diff --git a/include/linux/module.h b/include/linux/module.h
-index c458418..627afb9 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -17,6 +17,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>
-@@ -348,6 +349,10 @@ struct module
- /* The command line arguments (may be mangled). People like
- keeping pointers to this stuff */
- char *args;
-+#ifdef CONFIG_MARKERS
-+ struct marker *markers;
-+ unsigned int num_markers;
-+#endif
- };
-
- /* FIXME: It'd be nice to isolate modules during init, too, so they
-@@ -467,6 +472,7 @@ int register_module_notifier(struct notifier_block * nb);
- int unregister_module_notifier(struct notifier_block * nb);
-
- extern void print_modules(void);
-+extern void module_update_markers(void);
-
- struct device_driver;
- void module_add_driver(struct module *, struct device_driver *);
-@@ -569,6 +575,10 @@ static inline void print_modules(void)
- {
- }
-
-+static inline void module_update_markers(void)
-+{
-+}
-+
- struct device_driver;
- struct module;
-
-diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
-index b4ca73d..5f12d1b 100644
---- a/include/linux/rcupdate.h
-+++ b/include/linux/rcupdate.h
-@@ -42,6 +42,19 @@
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
-
-+/*
-+ * Prevent the compiler from merging or refetching accesses. The compiler
-+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
-+ * but only when the compiler is aware of some particular ordering. One way
-+ * to make the compiler aware of ordering is to put the two invocations of
-+ * ACCESS_ONCE() in different C statements.
-+ *
-+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
-+ * merging, or refetching absolutely anything at any time.
-+ *
-+ */
-+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-+
- /**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
-diff --git a/kernel/Makefile b/kernel/Makefile
-index ed4af9c..b4ad7a7 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
- obj-$(CONFIG_RELAY) += relay.o
- obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
- obj-$(CONFIG_TASKSTATS) += taskstats.o
-+obj-$(CONFIG_MARKERS) += marker.o
- obj-$(CONFIG_UTRACE) += utrace.o
-
- ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
-diff --git a/kernel/marker.c b/kernel/marker.c
-new file mode 100644
-index 0000000..c4c2cd8
---- /dev/null
-+++ b/kernel/marker.c
-@@ -0,0 +1,851 @@
-+/*
-+ * 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 marker __start___markers[];
-+extern struct marker __stop___markers[];
-+
-+/* Set to 1 to enable marker debug output */
-+const int marker_debug;
-+
-+/*
-+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
-+ * and module markers and the hash table.
-+ */
-+static DEFINE_MUTEX(markers_mutex);
-+
-+/*
-+ * Marker hash table, containing the active markers.
-+ * Protected by module_mutex.
-+ */
-+#define MARKER_HASH_BITS 6
-+#define MARKER_TABLE_SIZE (1 << MARKER_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 marker. It is
-+ * also used to delay the free of multiple probes array until a quiescent state
-+ * is reached.
-+ * marker entries modifications are protected by the markers_mutex.
-+ */
-+struct marker_entry {
-+ struct hlist_node hlist;
-+ char *format;
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+ int refcount; /* Number of times armed. 0 if disarmed. */
-+ struct rcu_head rcu;
-+ void *oldptr;
-+ char rcu_pending:1;
-+ char ptype:1;
-+ char name[0]; /* Contains name'\0'format'\0' */
-+};
-+
-+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
-+
-+/**
-+ * __mark_empty_function - Empty probe callback
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args)
-+{
-+}
-+EXPORT_SYMBOL_GPL(__mark_empty_function);
-+
-+/*
-+ * marker_probe_cb Callback that prepares the variable argument list for probes.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Since we do not use "typical" pointer based RCU in the 1 argument case, we
-+ * need to put a full smp_rmb() in this branch. This is why we do not use
-+ * rcu_dereference() for the pointer read.
-+ */
-+void marker_probe_cb(const struct marker *mdata, void *call_private,
-+ const char *fmt, ...)
-+{
-+ va_list args;
-+ char ptype;
-+
-+ /*
-+ * disabling preemption to make sure the teardown of the callbacks can
-+ * be done correctly when they are in modules and they insure RCU read
-+ * coherency.
-+ */
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ va_start(args, fmt);
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ va_end(args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++) {
-+ va_start(args, fmt);
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ va_end(args);
-+ }
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb);
-+
-+/*
-+ * marker_probe_cb Callback that does not prepare the variable argument list.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Should be connected to markers "MARK_NOARGS".
-+ */
-+void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...)
-+{
-+ va_list args; /* not initialized */
-+ char ptype;
-+
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++)
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
-+
-+static void free_old_closure(struct rcu_head *head)
-+{
-+ struct marker_entry *entry = container_of(head,
-+ struct marker_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 marker_entry *entry)
-+{
-+ int i;
-+
-+ if (!marker_debug)
-+ return;
-+
-+ if (!entry->ptype) {
-+ printk(KERN_DEBUG "Single probe : %p %p\n",
-+ entry->single.func,
-+ entry->single.probe_private);
-+ } else {
-+ 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 marker_probe_closure *
-+marker_entry_add_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0;
-+ struct marker_probe_closure *old, *new;
-+
-+ WARN_ON(!probe);
-+
-+ debug_print_probes(entry);
-+ old = entry->multi;
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe &&
-+ entry->single.probe_private == probe_private)
-+ return ERR_PTR(-EBUSY);
-+ if (entry->single.func == __mark_empty_function) {
-+ /* 0 -> 1 probes */
-+ entry->single.func = probe;
-+ entry->single.probe_private = probe_private;
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* 1 -> 2 probes */
-+ nr_probes = 1;
-+ old = NULL;
-+ }
-+ } else {
-+ /* (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 marker_probe_closure),
-+ GFP_KERNEL);
-+ if (new == NULL)
-+ return ERR_PTR(-ENOMEM);
-+ if (!old)
-+ new[0] = entry->single;
-+ else
-+ memcpy(new, old,
-+ nr_probes * sizeof(struct marker_probe_closure));
-+ new[nr_probes].func = probe;
-+ new[nr_probes].probe_private = probe_private;
-+ entry->refcount = nr_probes + 1;
-+ entry->multi = new;
-+ entry->ptype = 1;
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+static struct marker_probe_closure *
-+marker_entry_remove_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0, nr_del = 0, i;
-+ struct marker_probe_closure *old, *new;
-+
-+ old = entry->multi;
-+
-+ debug_print_probes(entry);
-+ if (!entry->ptype) {
-+ /* 0 -> N is an error */
-+ WARN_ON(entry->single.func == __mark_empty_function);
-+ /* 1 -> 0 probes */
-+ WARN_ON(probe && entry->single.func != probe);
-+ WARN_ON(entry->single.probe_private != probe_private);
-+ entry->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* (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->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ } else if (nr_probes - nr_del == 1) {
-+ /* N -> 1, (N > 1) */
-+ for (i = 0; old[i].func; i++)
-+ if ((probe && old[i].func != probe) ||
-+ old[i].probe_private != probe_private)
-+ entry->single = old[i];
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ } else {
-+ int j = 0;
-+ /* N -> M, (N > 1, M > 1) */
-+ /* + 1 for NULL */
-+ new = kzalloc((nr_probes - nr_del + 1)
-+ * sizeof(struct marker_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->ptype = 1;
-+ entry->multi = new;
-+ }
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+/*
-+ * 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 struct marker_entry *add_marker(const char *name, const char *format)
-+{
-+ 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\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 marker_entry) + name_len + format_len,
-+ GFP_KERNEL);
-+ if (!e)
-+ return ERR_PTR(-ENOMEM);
-+ memcpy(&e->name[0], name, name_len);
-+ if (format) {
-+ e->format = &e->name[name_len];
-+ memcpy(e->format, format, format_len);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ trace_mark(core_marker_format, "name %s format %s",
-+ e->name, e->format);
-+ } else {
-+ e->format = NULL;
-+ e->call = marker_probe_cb;
-+ }
-+ e->single.func = __mark_empty_function;
-+ e->single.probe_private = NULL;
-+ e->multi = NULL;
-+ e->ptype = 0;
-+ e->refcount = 0;
-+ e->rcu_pending = 0;
-+ hlist_add_head(&e->hlist, head);
-+ return e;
-+}
-+
-+/*
-+ * Remove the marker from the marker hash table. Must be called with mutex_lock
-+ * held.
-+ */
-+static int 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;
-+ 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)
-+ return -ENOENT;
-+ if (e->single.func != __mark_empty_function)
-+ return -EBUSY;
-+ hlist_del(&e->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if (e->rcu_pending)
-+ rcu_barrier();
-+ kfree(e);
-+ return 0;
-+}
-+
-+/*
-+ * 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);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ e->single = (*entry)->single;
-+ e->multi = (*entry)->multi;
-+ e->ptype = (*entry)->ptype;
-+ e->refcount = (*entry)->refcount;
-+ e->rcu_pending = 0;
-+ hlist_add_before(&e->hlist, &(*entry)->hlist);
-+ hlist_del(&(*entry)->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if ((*entry)->rcu_pending)
-+ rcu_barrier();
-+ 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 marker *elem,
-+ int active)
-+{
-+ 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;
-+ }
-+
-+ /*
-+ * probe_cb setup (statically known) is done here. It is
-+ * asynchronous with the rest of execution, therefore we only
-+ * pass from a "safe" callback (with argument) to an "unsafe"
-+ * callback (does not set arguments).
-+ */
-+ elem->call = (*entry)->call;
-+ /*
-+ * Sanity check :
-+ * We only update the single probe private data when the ptr is
-+ * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
-+ */
-+ WARN_ON(elem->single.func != __mark_empty_function
-+ && elem->single.probe_private
-+ != (*entry)->single.probe_private &&
-+ !elem->ptype);
-+ elem->single.probe_private = (*entry)->single.probe_private;
-+ /*
-+ * Make sure the private data is valid when we update the
-+ * single probe ptr.
-+ */
-+ smp_wmb();
-+ elem->single.func = (*entry)->single.func;
-+ /*
-+ * 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);
-+ /*
-+ * Update the function or multi probe array pointer before setting the
-+ * ptype.
-+ */
-+ smp_wmb();
-+ elem->ptype = (*entry)->ptype;
-+ elem->state = active;
-+
-+ 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 marker *elem)
-+{
-+ /* leave "call" as is. It is known statically. */
-+ elem->state = 0;
-+ elem->single.func = __mark_empty_function;
-+ /* Update the function before setting the ptype */
-+ smp_wmb();
-+ elem->ptype = 0; /* single probe */
-+ /*
-+ * 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
-+ *
-+ * Updates the probe callback corresponding to a range of markers.
-+ */
-+void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{
-+ struct marker *iter;
-+ struct marker_entry *mark_entry;
-+
-+ mutex_lock(&markers_mutex);
-+ for (iter = begin; iter < end; iter++) {
-+ mark_entry = get_marker(iter->name);
-+ if (mark_entry) {
-+ set_marker(&mark_entry, iter,
-+ !!mark_entry->refcount);
-+ /*
-+ * ignore error, continue
-+ */
-+ } else {
-+ disable_marker(iter);
-+ }
-+ }
-+ mutex_unlock(&markers_mutex);
-+}
-+
-+/*
-+ * 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.
-+ *
-+ * Internal callback only changed before the first probe is connected to it.
-+ * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
-+ * transitions. All other transitions will leave the old private data valid.
-+ * This makes the non-atomicity of the callback/private data updates valid.
-+ *
-+ * "special case" updates :
-+ * 0 -> 1 callback
-+ * 1 -> 0 callback
-+ * 1 -> 2 callbacks
-+ * 2 -> 1 callbacks
-+ * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
-+ * Site effect : marker_set_format may delete the marker entry (creating a
-+ * replacement).
-+ */
-+static void marker_update_probes(void)
-+{
-+ /* Core kernel markers */
-+ marker_update_probe_range(__start___markers, __stop___markers);
-+ /* Markers in modules. */
-+ module_update_markers();
-+}
-+
-+/**
-+ * marker_probe_register - Connect a probe to a marker
-+ * @name: marker name
-+ * @format: format string
-+ * @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 marker_probe_register(const char *name, const char *format,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ entry = add_marker(name, format);
-+ if (IS_ERR(entry)) {
-+ ret = PTR_ERR(entry);
-+ goto end;
-+ }
-+ }
-+ /*
-+ * If we detect that a call_rcu is pending for this marker,
-+ * make sure it's executed now.
-+ */
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_add_probe(entry, probe, probe_private);
-+ if (IS_ERR(old)) {
-+ ret = PTR_ERR(old);
-+ goto end;
-+ }
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_register);
-+
-+/**
-+ * marker_probe_unregister - Disconnect a probe from a marker
-+ * @name: marker name
-+ * @probe: probe function pointer
-+ * @probe_private: probe private data
-+ *
-+ * Returns the private data given to marker_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 marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ struct marker_probe_closure *old;
-+ int ret = 0;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, probe, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister);
-+
-+static struct marker_entry *
-+get_marker_from_private_data(marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ unsigned int i;
-+ struct hlist_head *head;
-+ struct hlist_node *node;
-+
-+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-+ head = &marker_table[i];
-+ hlist_for_each_entry(entry, node, head, hlist) {
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe
-+ && entry->single.probe_private
-+ == probe_private)
-+ return entry;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ closure = entry->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func == probe &&
-+ closure[i].probe_private
-+ == probe_private)
-+ return entry;
-+ }
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
-+ * @probe: probe function
-+ * @probe_private: probe private data
-+ *
-+ * Unregister a probe by providing the registered private data.
-+ * Only removes the first marker found in hash table.
-+ * Return 0 on success or error value.
-+ * 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 marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, NULL, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(entry->name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
-+
-+/**
-+ * marker_get_private_data - Get a marker's probe private data
-+ * @name: marker name
-+ * @probe: probe to match
-+ * @num: get the nth matching probe's private data
-+ *
-+ * Returns the nth private data pointer (starting from 0) matching, or an
-+ * ERR_PTR.
-+ * 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, marker_probe_func *probe,
-+ int num)
-+{
-+ 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 i;
-+
-+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
-+ hlist_for_each_entry(e, node, head, hlist) {
-+ if (!strcmp(name, e->name)) {
-+ if (!e->ptype) {
-+ if (num == 0 && e->single.func == probe)
-+ return e->single.probe_private;
-+ else
-+ break;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ int match = 0;
-+ closure = e->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func != probe)
-+ continue;
-+ if (match++ == num)
-+ return closure[i].probe_private;
-+ }
-+ }
-+ }
-+ }
-+ return ERR_PTR(-ENOENT);
-+}
-+EXPORT_SYMBOL_GPL(marker_get_private_data);
-diff --git a/kernel/module.c b/kernel/module.c
-index f9a5987..ac99222 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1488,6 +1488,8 @@ static struct module *load_module(void __user *umod,
- 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 */
-@@ -1756,6 +1758,9 @@ static struct module *load_module(void __user *umod,
- add_taint(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++) {
-@@ -1778,6 +1783,11 @@ static struct module *load_module(void __user *umod,
- 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);
-@@ -1796,6 +1806,11 @@ static struct module *load_module(void __user *umod,
-
- add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-
-+#ifdef CONFIG_MARKERS
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+#endif
- err = module_finalize(hdr, sechdrs, mod);
- if (err < 0)
- goto cleanup;
-@@ -2259,3 +2274,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(void)
-+{
-+ struct module *mod;
-+
-+ mutex_lock(&module_mutex);
-+ list_for_each_entry(mod, &modules, list)
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+ mutex_unlock(&module_mutex);
-+}
-+#endif
-+
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index 0a64688..886b70c 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -13,6 +13,7 @@
- # 2) modpost is then used to
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
-+# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
- # 5) compile all <module>.mod.c files
- # 6) final link of the module to a <module.ko> file
-
-@@ -41,6 +42,10 @@ include scripts/Makefile.lib
-
- kernelsymfile := $(objtree)/Module.symvers
- modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
-+kernelmarkersfile := $(objtree)/Module.markers
-+modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
-+
-+markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
-
- # Step 1), find all modules listed in $(MODVERDIR)/
- __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
-@@ -58,16 +63,27 @@ quiet_cmd_modpost = MODPOST
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
-+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
-+ $(if $(CONFIG_MARKERS),-M $(markersfile)) \
- $(filter-out FORCE,$^)
-
- PHONY += __modpost
- __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
- $(call cmd,modpost)
-
-+quiet_cmd_kernel-mod = MODPOST $@
-+ cmd_kernel-mod = $(cmd_modpost) $@
-+
-+vmlinux.o: FORCE
-+ $(call cmd,kernel-mod)
-+
- # Declare generated files as targets for modpost
- $(symverfile): __modpost ;
- $(modules:.ko=.mod.c): __modpost ;
-
-+ifdef CONFIG_MARKERS
-+$(markersfile): __modpost ;
-+endif
-
- # Step 5), compile all *.mod.c files
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index dfde0e8..81e5910 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -10,7 +10,8 @@
- *
- * Usage: modpost vmlinux module1.o module2.o ...
- */
--
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <ctype.h>
- #include "modpost.h"
- #include "../../include/linux/license.h"
-@@ -385,6 +386,8 @@ static void parse_elf(struct elf_info *info, const char *filename)
- info->export_unused_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
- info->export_gpl_future_sec = i;
-+ else if (strcmp(secname, "__markers_strings") == 0)
-+ info->markers_strings_sec = i;
-
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
-@@ -859,6 +862,62 @@ static void check_sec_ref(struct module *mod, const char *modname,
- }
- }
-
-+static void get_markers(struct elf_info *info, struct module *mod)
-+{
-+ const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-+ const char *strings = (const char *) info->hdr + sh->sh_offset;
-+ const Elf_Sym *sym, *first_sym, *last_sym;
-+ size_t n;
-+
-+ if (!info->markers_strings_sec)
-+ return;
-+
-+ /*
-+ * First count the strings. We look for all the symbols defined
-+ * in the __markers_strings section named __mstrtab_*. For
-+ * these local names, the compiler puts a random .NNN suffix on,
-+ * so the names don't correspond exactly.
-+ */
-+ first_sym = last_sym = NULL;
-+ n = 0;
-+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ if (first_sym == NULL)
-+ first_sym = sym;
-+ last_sym = sym;
-+ ++n;
-+ }
-+
-+ if (n == 0)
-+ return;
-+
-+ /*
-+ * Now collect each name and format into a line for the output.
-+ * Lines look like:
-+ * marker_name vmlinux marker %s format %d
-+ * The format string after the second \t can use whitespace.
-+ */
-+ mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-+ mod->nmarkers = n;
-+
-+ n = 0;
-+ for (sym = first_sym; sym <= last_sym; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ const char *name = strings + sym->st_value;
-+ const char *fmt = strchr(name, '\0') + 1;
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+ mod->markers[n++] = line;
-+ }
-+}
-+
- /**
- * Functions used only during module init is marked __init and is stored in
- * a .init.text section. Likewise data is marked __initdata and stored in
-@@ -1061,6 +1120,8 @@ static void read_symbols(char *modname)
- get_src_version(modname, mod->srcversion,
- sizeof(mod->srcversion)-1);
-
-+ get_markers(&info, mod);
-+
- parse_elf_finish(&info);
-
- /* Our trick to get versioning for struct_module - it's
-@@ -1394,6 +1455,93 @@ static void write_dump(const char *fname)
- write_if_changed(&buf, fname);
- }
-
-+static void add_marker(struct module *mod, const char *name, const char *fmt)
-+{
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+
-+ mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-+ sizeof mod->markers[0])));
-+ mod->markers[mod->nmarkers++] = line;
-+}
-+
-+static void read_markers(const char *fname)
-+{
-+ unsigned long size, pos = 0;
-+ void *file = grab_file(fname, &size);
-+ char *line;
-+
-+ if (!file) /* No old markers, silently ignore */
-+ return;
-+
-+ while ((line = get_next_line(&pos, file, size))) {
-+ char *marker, *modname, *fmt;
-+ struct module *mod;
-+
-+ marker = line;
-+ modname = strchr(marker, '\t');
-+ if (!modname)
-+ goto fail;
-+ *modname++ = '\0';
-+ fmt = strchr(modname, '\t');
-+ if (!fmt)
-+ goto fail;
-+ *fmt++ = '\0';
-+ if (*marker == '\0' || *modname == '\0')
-+ goto fail;
-+
-+ mod = find_module(modname);
-+ if (!mod) {
-+ if (is_vmlinux(modname))
-+ have_vmlinux = 1;
-+ mod = new_module(NOFAIL(strdup(modname)));
-+ mod->skip = 1;
-+ }
-+
-+ add_marker(mod, marker, fmt);
-+ }
-+ return;
-+fail:
-+ fatal("parse error in markers list file\n");
-+}
-+
-+static int compare_strings(const void *a, const void *b)
-+{
-+ return strcmp(*(const char **) a, *(const char **) b);
-+}
-+
-+static void write_markers(const char *fname)
-+{
-+ struct buffer buf = { };
-+ struct module *mod;
-+ size_t i;
-+
-+ for (mod = modules; mod; mod = mod->next)
-+ if ((!external_module || !mod->skip) && mod->markers != NULL) {
-+ /*
-+ * Sort the strings so we can skip duplicates when
-+ * we write them out.
-+ */
-+ qsort(mod->markers, mod->nmarkers,
-+ sizeof mod->markers[0], &compare_strings);
-+ for (i = 0; i < mod->nmarkers; ++i) {
-+ char *line = mod->markers[i];
-+ buf_write(&buf, line, strlen(line));
-+ while (i + 1 < mod->nmarkers &&
-+ !strcmp(mod->markers[i],
-+ mod->markers[i + 1]))
-+ free(mod->markers[i++]);
-+ free(mod->markers[i]);
-+ }
-+ free(mod->markers);
-+ mod->markers = NULL;
-+ }
-+
-+ write_if_changed(&buf, fname);
-+}
-+
-+
- int main(int argc, char **argv)
- {
- struct module *mod;
-@@ -1402,8 +1550,10 @@ int main(int argc, char **argv)
- char *kernel_read = NULL, *module_read = NULL;
- char *dump_write = NULL;
- int opt;
-+ char *markers_read = NULL;
-+ char *markers_write = NULL;
-
-- while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
-+ while ((opt = getopt(argc, argv, "i:I:mo:aM:K:")) != -1) {
- switch(opt) {
- case 'i':
- kernel_read = optarg;
-@@ -1421,6 +1571,12 @@ int main(int argc, char **argv)
- case 'a':
- all_versions = 1;
- break;
-+ case 'M':
-+ markers_write = optarg;
-+ break;
-+ case 'K':
-+ markers_read = optarg;
-+ break;
- default:
- exit(1);
- }
-@@ -1460,5 +1616,11 @@ int main(int argc, char **argv)
- if (dump_write)
- write_dump(dump_write);
-
-+ if (markers_read)
-+ read_markers(markers_read);
-+
-+ if (markers_write)
-+ write_markers(markers_write);
-+
- return 0;
- }
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index d398c61..27b05e6 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -107,6 +107,8 @@ struct module {
- int has_init;
- int has_cleanup;
- struct buffer dev_table_buf;
-+ char **markers;
-+ size_t nmarkers;
- char srcversion[25];
- };
-
-@@ -121,6 +123,7 @@ struct elf_info {
- Elf_Section export_gpl_sec;
- Elf_Section export_unused_gpl_sec;
- Elf_Section export_gpl_future_sec;
-+ Elf_Section markers_strings_sec;
- const char *strtab;
- char *modinfo;
- unsigned int modinfo_len;
Deleted: trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5u1.patch
===================================================================
--- trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5u1.patch 2008-07-04 02:18:23 UTC (rev 6)
+++ trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.18.el5u1.patch 2008-07-04 02:22:00 UTC (rev 7)
@@ -1,1882 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 93bffdf..59693ac 100644
---- a/Makefile
-+++ b/Makefile
-@@ -603,7 +603,7 @@ quiet_cmd_vmlinux__ ?= LD $@
- cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
- --start-group $(vmlinux-main) --end-group \
-- $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
-+ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
-
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN .version
-@@ -727,11 +727,30 @@ debug_kallsyms: .tmp_map$(last_kallsyms)
-
- endif # ifdef CONFIG_KALLSYMS
-
-+# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
-+# relevant sections renamed as per the linker script.
-+quiet_cmd_vmlinux-modpost = LD $@
-+ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
-+ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
-+ $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
-+define rule_vmlinux-modpost
-+ :
-+ +$(call cmd,vmlinux-modpost)
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
-+ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
-+endef
-+
- # vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
-+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
-+ $(call vmlinux-modpost)
- $(call if_changed_rule,vmlinux__)
- $(Q)rm -f .old_version
-
-+# build vmlinux.o first to catch section mismatch errors early
-+$(kallsyms.o): vmlinux.o
-+vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
-+ $(call if_changed_rule,vmlinux-modpost)
-+
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
-index d04fcc6..ad73af5 100644
---- a/arch/i386/Kconfig
-+++ b/arch/i386/Kconfig
-@@ -1212,6 +1212,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/i386/Kconfig.debug"
-diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
-index 7f4ca6b..3978095 100644
---- a/arch/i386/kernel/vmlinux.lds.S
-+++ b/arch/i386/kernel/vmlinux.lds.S
-@@ -67,6 +67,7 @@ SECTIONS
- . = ALIGN(4096);
- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- } :data
-
-diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index f916fba..b81a36b 100644
---- a/arch/ia64/Kconfig
-+++ b/arch/ia64/Kconfig
-@@ -591,6 +591,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/ia64/Kconfig.debug"
-diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
-index 69cba94..2c0a5c9 100644
---- a/arch/ia64/kernel/vmlinux.lds.S
-+++ b/arch/ia64/kernel/vmlinux.lds.S
-@@ -207,7 +207,7 @@ SECTIONS
-
- data : { } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET)
-- { *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
-+ { *(.data) *(.data1) *(.gnu.linkonce.d*) MARKER CONSTRUCTORS }
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET)
-diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 7295252..fb8a2b9 100644
---- a/arch/powerpc/Kconfig
-+++ b/arch/powerpc/Kconfig
-@@ -1091,6 +1091,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/powerpc/Kconfig.debug"
-diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
-index c02298a..709bc47 100644
---- a/arch/powerpc/kernel/vmlinux.lds.S
-+++ b/arch/powerpc/kernel/vmlinux.lds.S
-@@ -176,11 +176,13 @@ SECTIONS
- *(.data)
- *(.sdata)
- *(.got.plt) *(.got)
-+ MARKER
- }
- #else
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
-+ MARKER
- }
-
- .opd : {
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index d121403..d8d276a 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -503,6 +503,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/s390/Kconfig.debug"
-diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
-index af9e69a..8443156 100644
---- a/arch/s390/kernel/vmlinux.lds.S
-+++ b/arch/s390/kernel/vmlinux.lds.S
-@@ -46,6 +46,7 @@ SECTIONS
-
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
-index b627f8d..e0467d1 100644
---- a/arch/sparc64/Kconfig
-+++ b/arch/sparc64/Kconfig
-@@ -427,6 +427,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/sparc64/Kconfig.debug"
-diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
-index b097379..1f10e43 100644
---- a/arch/sparc64/kernel/vmlinux.lds.S
-+++ b/arch/sparc64/kernel/vmlinux.lds.S
-@@ -27,6 +27,7 @@ SECTIONS
- .data :
- {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
-diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
-index 651d6cb..0e6570c 100644
---- a/arch/x86_64/Kconfig
-+++ b/arch/x86_64/Kconfig
-@@ -711,6 +711,14 @@ config KPROBES
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-+
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- endmenu
-
- source "arch/x86_64/Kconfig.debug"
-diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
-index 57e3255..867fce1 100644
---- a/arch/x86_64/kernel/vmlinux.lds.S
-+++ b/arch/x86_64/kernel/vmlinux.lds.S
-@@ -68,6 +68,7 @@ SECTIONS
- /* Data */
- .data : AT(ADDR(.data) - LOAD_OFFSET) {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- } :data
-
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 3fb354d..e884942 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -126,7 +126,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
- // ================= 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 port *port, int lacp_fast);
- 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);
-
-
- /////////////////////////////////////////////////////////////////////////////////
-@@ -912,12 +912,13 @@ static int ad_lacpdu_send(struct port *port)
- * 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);
-@@ -932,7 +933,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
- skb->nh.raw = skb->data + 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
-@@ -1732,7 +1733,7 @@ static void ad_disable_collecting_distributing(struct port *port)
- */
- 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
-@@ -1765,13 +1766,14 @@ static void ad_marker_info_send(struct port *port)
- * @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
-@@ -1790,7 +1792,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
- * 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
-@@ -2187,15 +2190,16 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
- 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:
-diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
-index 6ad5ad6..bf93e7e 100644
---- a/drivers/net/bonding/bond_3ad.h
-+++ b/drivers/net/bonding/bond_3ad.h
-@@ -92,7 +92,8 @@ 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 +149,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 +162,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()
-
-diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
-index 8c6f9b6..efc3d79 100644
---- a/drivers/scsi/qla4xxx/ql4_fw.h
-+++ b/drivers/scsi/qla4xxx/ql4_fw.h
-@@ -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 */
-diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
-index d45e4d0..b85a484 100644
---- a/drivers/scsi/qla4xxx/ql4_iocb.c
-+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
-@@ -70,7 +70,8 @@ int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
- 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;
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index b9e964c..a175f1e 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -9,12 +9,21 @@
- /* Align . to a 8 byte boundary equals to maximum function alignment. */
- #define ALIGN_FUNCTION() . = ALIGN(8)
-
-+/* Kernel markers : pointers */
-+#define MARKER \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__start___markers) = .; \
-+ *(__markers) \
-+ VMLINUX_SYMBOL(__stop___markers) = .;
-+
-+
- #define RODATA \
- . = ALIGN(4096); \
- .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_rodata) = .; \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
-+ *(__markers_strings) /* Markers: strings */ \
- } \
- \
- .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
-diff --git a/include/linux/marker.h b/include/linux/marker.h
-new file mode 100644
-index 0000000..efbc82b
---- /dev/null
-+++ b/include/linux/marker.h
-@@ -0,0 +1,139 @@
-+#ifndef _LINUX_MARKER_H
-+#define _LINUX_MARKER_H
-+
-+/*
-+ * Code markup for dynamic and static tracing.
-+ *
-+ * See Documentation/marker.txt.
-+ *
-+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
-+ *
-+ * This file is released under the GPLv2.
-+ * See the file COPYING for more details.
-+ */
-+
-+#include <linux/types.h>
-+
-+struct module;
-+struct marker;
-+
-+/**
-+ * marker_probe_func - Type of a marker probe function
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @fmt: format string
-+ * @args: variable argument list pointer. Use a pointer to overcome C's
-+ * inability to pass this around as a pointer in a portable manner in
-+ * the callee otherwise.
-+ *
-+ * 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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args);
-+
-+struct marker_probe_closure {
-+ marker_probe_func *func; /* Callback */
-+ void *probe_private; /* Private probe data */
-+};
-+
-+struct marker {
-+ const char *name; /* Marker name */
-+ const char *format; /* Marker format string, describing the
-+ * variable argument list.
-+ */
-+ char state; /* Marker state. */
-+ char ptype; /* probe type : 0 : single, 1 : multi */
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+} __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_private, format, args...) \
-+ do { \
-+ static const char __mstrtab_##name[] \
-+ __attribute__((section("__markers_strings"))) \
-+ = #name "\0" format; \
-+ static struct marker __mark_##name \
-+ __attribute__((section("__markers"), aligned(8))) = \
-+ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
-+ 0, 0, marker_probe_cb, \
-+ { __mark_empty_function, NULL}, NULL }; \
-+ __mark_check_format(format, ## args); \
-+ if (unlikely(__mark_##name.state)) { \
-+ (*__mark_##name.call) \
-+ (&__mark_##name, call_private, \
-+ format, ## args); \
-+ } \
-+ } while (0)
-+
-+extern void marker_update_probe_range(struct marker *begin,
-+ struct marker *end);
-+#else /* !CONFIG_MARKERS */
-+#define __trace_mark(name, call_private, format, args...) \
-+ __mark_check_format(format, ## args)
-+static inline void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{ }
-+#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)
-+
-+/**
-+ * 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 __attribute__ ((format (printf, 1, 2))) __mark_check_format(const char *fmt, ...)
-+{
-+}
-+
-+extern marker_probe_func __mark_empty_function;
-+
-+extern void marker_probe_cb(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+extern void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+
-+/*
-+ * 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 *probe_private);
-+
-+/*
-+ * Returns the private data given to marker_probe_register.
-+ */
-+extern int marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private);
-+/*
-+ * Unregister a marker by providing the registered private data.
-+ */
-+extern int marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private);
-+
-+extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
-+ int num);
-+
-+#endif
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 0460634..de5b51e 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -17,6 +17,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>
-@@ -353,6 +354,10 @@ struct module
- /* The command line arguments (may be mangled). People like
- keeping pointers to this stuff */
- char *args;
-+#ifdef CONFIG_MARKERS
-+ struct marker *markers;
-+ unsigned int num_markers;
-+#endif
- };
-
- /* FIXME: It'd be nice to isolate modules during init, too, so they
-@@ -472,6 +477,7 @@ int register_module_notifier(struct notifier_block * nb);
- int unregister_module_notifier(struct notifier_block * nb);
-
- extern void print_modules(void);
-+extern void module_update_markers(void);
-
- struct device_driver;
- void module_add_driver(struct module *, struct device_driver *);
-@@ -574,6 +580,10 @@ static inline void print_modules(void)
- {
- }
-
-+static inline void module_update_markers(void)
-+{
-+}
-+
- struct device_driver;
- struct module;
-
-diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
-index b4ca73d..5f12d1b 100644
---- a/include/linux/rcupdate.h
-+++ b/include/linux/rcupdate.h
-@@ -42,6 +42,19 @@
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
-
-+/*
-+ * Prevent the compiler from merging or refetching accesses. The compiler
-+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
-+ * but only when the compiler is aware of some particular ordering. One way
-+ * to make the compiler aware of ordering is to put the two invocations of
-+ * ACCESS_ONCE() in different C statements.
-+ *
-+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
-+ * merging, or refetching absolutely anything at any time.
-+ *
-+ */
-+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-+
- /**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
-diff --git a/kernel/Makefile b/kernel/Makefile
-index ef832fa..5879e8b 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
- obj-$(CONFIG_RELAY) += relay.o
- obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
- obj-$(CONFIG_TASKSTATS) += taskstats.o
-+obj-$(CONFIG_MARKERS) += marker.o
- obj-$(CONFIG_UTRACE) += utrace.o
- obj-$(CONFIG_PTRACE) += ptrace.o
-
-diff --git a/kernel/marker.c b/kernel/marker.c
-new file mode 100644
-index 0000000..c4c2cd8
---- /dev/null
-+++ b/kernel/marker.c
-@@ -0,0 +1,851 @@
-+/*
-+ * 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 marker __start___markers[];
-+extern struct marker __stop___markers[];
-+
-+/* Set to 1 to enable marker debug output */
-+const int marker_debug;
-+
-+/*
-+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
-+ * and module markers and the hash table.
-+ */
-+static DEFINE_MUTEX(markers_mutex);
-+
-+/*
-+ * Marker hash table, containing the active markers.
-+ * Protected by module_mutex.
-+ */
-+#define MARKER_HASH_BITS 6
-+#define MARKER_TABLE_SIZE (1 << MARKER_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 marker. It is
-+ * also used to delay the free of multiple probes array until a quiescent state
-+ * is reached.
-+ * marker entries modifications are protected by the markers_mutex.
-+ */
-+struct marker_entry {
-+ struct hlist_node hlist;
-+ char *format;
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+ int refcount; /* Number of times armed. 0 if disarmed. */
-+ struct rcu_head rcu;
-+ void *oldptr;
-+ char rcu_pending:1;
-+ char ptype:1;
-+ char name[0]; /* Contains name'\0'format'\0' */
-+};
-+
-+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
-+
-+/**
-+ * __mark_empty_function - Empty probe callback
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args)
-+{
-+}
-+EXPORT_SYMBOL_GPL(__mark_empty_function);
-+
-+/*
-+ * marker_probe_cb Callback that prepares the variable argument list for probes.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Since we do not use "typical" pointer based RCU in the 1 argument case, we
-+ * need to put a full smp_rmb() in this branch. This is why we do not use
-+ * rcu_dereference() for the pointer read.
-+ */
-+void marker_probe_cb(const struct marker *mdata, void *call_private,
-+ const char *fmt, ...)
-+{
-+ va_list args;
-+ char ptype;
-+
-+ /*
-+ * disabling preemption to make sure the teardown of the callbacks can
-+ * be done correctly when they are in modules and they insure RCU read
-+ * coherency.
-+ */
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ va_start(args, fmt);
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ va_end(args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++) {
-+ va_start(args, fmt);
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ va_end(args);
-+ }
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb);
-+
-+/*
-+ * marker_probe_cb Callback that does not prepare the variable argument list.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Should be connected to markers "MARK_NOARGS".
-+ */
-+void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...)
-+{
-+ va_list args; /* not initialized */
-+ char ptype;
-+
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++)
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
-+
-+static void free_old_closure(struct rcu_head *head)
-+{
-+ struct marker_entry *entry = container_of(head,
-+ struct marker_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 marker_entry *entry)
-+{
-+ int i;
-+
-+ if (!marker_debug)
-+ return;
-+
-+ if (!entry->ptype) {
-+ printk(KERN_DEBUG "Single probe : %p %p\n",
-+ entry->single.func,
-+ entry->single.probe_private);
-+ } else {
-+ 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 marker_probe_closure *
-+marker_entry_add_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0;
-+ struct marker_probe_closure *old, *new;
-+
-+ WARN_ON(!probe);
-+
-+ debug_print_probes(entry);
-+ old = entry->multi;
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe &&
-+ entry->single.probe_private == probe_private)
-+ return ERR_PTR(-EBUSY);
-+ if (entry->single.func == __mark_empty_function) {
-+ /* 0 -> 1 probes */
-+ entry->single.func = probe;
-+ entry->single.probe_private = probe_private;
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* 1 -> 2 probes */
-+ nr_probes = 1;
-+ old = NULL;
-+ }
-+ } else {
-+ /* (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 marker_probe_closure),
-+ GFP_KERNEL);
-+ if (new == NULL)
-+ return ERR_PTR(-ENOMEM);
-+ if (!old)
-+ new[0] = entry->single;
-+ else
-+ memcpy(new, old,
-+ nr_probes * sizeof(struct marker_probe_closure));
-+ new[nr_probes].func = probe;
-+ new[nr_probes].probe_private = probe_private;
-+ entry->refcount = nr_probes + 1;
-+ entry->multi = new;
-+ entry->ptype = 1;
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+static struct marker_probe_closure *
-+marker_entry_remove_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0, nr_del = 0, i;
-+ struct marker_probe_closure *old, *new;
-+
-+ old = entry->multi;
-+
-+ debug_print_probes(entry);
-+ if (!entry->ptype) {
-+ /* 0 -> N is an error */
-+ WARN_ON(entry->single.func == __mark_empty_function);
-+ /* 1 -> 0 probes */
-+ WARN_ON(probe && entry->single.func != probe);
-+ WARN_ON(entry->single.probe_private != probe_private);
-+ entry->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* (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->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ } else if (nr_probes - nr_del == 1) {
-+ /* N -> 1, (N > 1) */
-+ for (i = 0; old[i].func; i++)
-+ if ((probe && old[i].func != probe) ||
-+ old[i].probe_private != probe_private)
-+ entry->single = old[i];
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ } else {
-+ int j = 0;
-+ /* N -> M, (N > 1, M > 1) */
-+ /* + 1 for NULL */
-+ new = kzalloc((nr_probes - nr_del + 1)
-+ * sizeof(struct marker_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->ptype = 1;
-+ entry->multi = new;
-+ }
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+/*
-+ * 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 struct marker_entry *add_marker(const char *name, const char *format)
-+{
-+ 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\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 marker_entry) + name_len + format_len,
-+ GFP_KERNEL);
-+ if (!e)
-+ return ERR_PTR(-ENOMEM);
-+ memcpy(&e->name[0], name, name_len);
-+ if (format) {
-+ e->format = &e->name[name_len];
-+ memcpy(e->format, format, format_len);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ trace_mark(core_marker_format, "name %s format %s",
-+ e->name, e->format);
-+ } else {
-+ e->format = NULL;
-+ e->call = marker_probe_cb;
-+ }
-+ e->single.func = __mark_empty_function;
-+ e->single.probe_private = NULL;
-+ e->multi = NULL;
-+ e->ptype = 0;
-+ e->refcount = 0;
-+ e->rcu_pending = 0;
-+ hlist_add_head(&e->hlist, head);
-+ return e;
-+}
-+
-+/*
-+ * Remove the marker from the marker hash table. Must be called with mutex_lock
-+ * held.
-+ */
-+static int 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;
-+ 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)
-+ return -ENOENT;
-+ if (e->single.func != __mark_empty_function)
-+ return -EBUSY;
-+ hlist_del(&e->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if (e->rcu_pending)
-+ rcu_barrier();
-+ kfree(e);
-+ return 0;
-+}
-+
-+/*
-+ * 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);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ e->single = (*entry)->single;
-+ e->multi = (*entry)->multi;
-+ e->ptype = (*entry)->ptype;
-+ e->refcount = (*entry)->refcount;
-+ e->rcu_pending = 0;
-+ hlist_add_before(&e->hlist, &(*entry)->hlist);
-+ hlist_del(&(*entry)->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if ((*entry)->rcu_pending)
-+ rcu_barrier();
-+ 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 marker *elem,
-+ int active)
-+{
-+ 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;
-+ }
-+
-+ /*
-+ * probe_cb setup (statically known) is done here. It is
-+ * asynchronous with the rest of execution, therefore we only
-+ * pass from a "safe" callback (with argument) to an "unsafe"
-+ * callback (does not set arguments).
-+ */
-+ elem->call = (*entry)->call;
-+ /*
-+ * Sanity check :
-+ * We only update the single probe private data when the ptr is
-+ * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
-+ */
-+ WARN_ON(elem->single.func != __mark_empty_function
-+ && elem->single.probe_private
-+ != (*entry)->single.probe_private &&
-+ !elem->ptype);
-+ elem->single.probe_private = (*entry)->single.probe_private;
-+ /*
-+ * Make sure the private data is valid when we update the
-+ * single probe ptr.
-+ */
-+ smp_wmb();
-+ elem->single.func = (*entry)->single.func;
-+ /*
-+ * 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);
-+ /*
-+ * Update the function or multi probe array pointer before setting the
-+ * ptype.
-+ */
-+ smp_wmb();
-+ elem->ptype = (*entry)->ptype;
-+ elem->state = active;
-+
-+ 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 marker *elem)
-+{
-+ /* leave "call" as is. It is known statically. */
-+ elem->state = 0;
-+ elem->single.func = __mark_empty_function;
-+ /* Update the function before setting the ptype */
-+ smp_wmb();
-+ elem->ptype = 0; /* single probe */
-+ /*
-+ * 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
-+ *
-+ * Updates the probe callback corresponding to a range of markers.
-+ */
-+void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{
-+ struct marker *iter;
-+ struct marker_entry *mark_entry;
-+
-+ mutex_lock(&markers_mutex);
-+ for (iter = begin; iter < end; iter++) {
-+ mark_entry = get_marker(iter->name);
-+ if (mark_entry) {
-+ set_marker(&mark_entry, iter,
-+ !!mark_entry->refcount);
-+ /*
-+ * ignore error, continue
-+ */
-+ } else {
-+ disable_marker(iter);
-+ }
-+ }
-+ mutex_unlock(&markers_mutex);
-+}
-+
-+/*
-+ * 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.
-+ *
-+ * Internal callback only changed before the first probe is connected to it.
-+ * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
-+ * transitions. All other transitions will leave the old private data valid.
-+ * This makes the non-atomicity of the callback/private data updates valid.
-+ *
-+ * "special case" updates :
-+ * 0 -> 1 callback
-+ * 1 -> 0 callback
-+ * 1 -> 2 callbacks
-+ * 2 -> 1 callbacks
-+ * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
-+ * Site effect : marker_set_format may delete the marker entry (creating a
-+ * replacement).
-+ */
-+static void marker_update_probes(void)
-+{
-+ /* Core kernel markers */
-+ marker_update_probe_range(__start___markers, __stop___markers);
-+ /* Markers in modules. */
-+ module_update_markers();
-+}
-+
-+/**
-+ * marker_probe_register - Connect a probe to a marker
-+ * @name: marker name
-+ * @format: format string
-+ * @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 marker_probe_register(const char *name, const char *format,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ entry = add_marker(name, format);
-+ if (IS_ERR(entry)) {
-+ ret = PTR_ERR(entry);
-+ goto end;
-+ }
-+ }
-+ /*
-+ * If we detect that a call_rcu is pending for this marker,
-+ * make sure it's executed now.
-+ */
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_add_probe(entry, probe, probe_private);
-+ if (IS_ERR(old)) {
-+ ret = PTR_ERR(old);
-+ goto end;
-+ }
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_register);
-+
-+/**
-+ * marker_probe_unregister - Disconnect a probe from a marker
-+ * @name: marker name
-+ * @probe: probe function pointer
-+ * @probe_private: probe private data
-+ *
-+ * Returns the private data given to marker_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 marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ struct marker_probe_closure *old;
-+ int ret = 0;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, probe, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister);
-+
-+static struct marker_entry *
-+get_marker_from_private_data(marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ unsigned int i;
-+ struct hlist_head *head;
-+ struct hlist_node *node;
-+
-+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-+ head = &marker_table[i];
-+ hlist_for_each_entry(entry, node, head, hlist) {
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe
-+ && entry->single.probe_private
-+ == probe_private)
-+ return entry;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ closure = entry->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func == probe &&
-+ closure[i].probe_private
-+ == probe_private)
-+ return entry;
-+ }
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
-+ * @probe: probe function
-+ * @probe_private: probe private data
-+ *
-+ * Unregister a probe by providing the registered private data.
-+ * Only removes the first marker found in hash table.
-+ * Return 0 on success or error value.
-+ * 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 marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, NULL, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(entry->name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
-+
-+/**
-+ * marker_get_private_data - Get a marker's probe private data
-+ * @name: marker name
-+ * @probe: probe to match
-+ * @num: get the nth matching probe's private data
-+ *
-+ * Returns the nth private data pointer (starting from 0) matching, or an
-+ * ERR_PTR.
-+ * 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, marker_probe_func *probe,
-+ int num)
-+{
-+ 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 i;
-+
-+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
-+ hlist_for_each_entry(e, node, head, hlist) {
-+ if (!strcmp(name, e->name)) {
-+ if (!e->ptype) {
-+ if (num == 0 && e->single.func == probe)
-+ return e->single.probe_private;
-+ else
-+ break;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ int match = 0;
-+ closure = e->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func != probe)
-+ continue;
-+ if (match++ == num)
-+ return closure[i].probe_private;
-+ }
-+ }
-+ }
-+ }
-+ return ERR_PTR(-ENOENT);
-+}
-+EXPORT_SYMBOL_GPL(marker_get_private_data);
-diff --git a/kernel/module.c b/kernel/module.c
-index f9a5987..ac99222 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1488,6 +1488,8 @@ static struct module *load_module(void __user *umod,
- 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 */
-@@ -1756,6 +1758,9 @@ static struct module *load_module(void __user *umod,
- add_taint(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++) {
-@@ -1778,6 +1783,11 @@ static struct module *load_module(void __user *umod,
- 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);
-@@ -1796,6 +1806,11 @@ static struct module *load_module(void __user *umod,
-
- add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-
-+#ifdef CONFIG_MARKERS
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+#endif
- err = module_finalize(hdr, sechdrs, mod);
- if (err < 0)
- goto cleanup;
-@@ -2259,3 +2274,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(void)
-+{
-+ struct module *mod;
-+
-+ mutex_lock(&module_mutex);
-+ list_for_each_entry(mod, &modules, list)
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+ mutex_unlock(&module_mutex);
-+}
-+#endif
-+
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index 0a64688..886b70c 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -13,6 +13,7 @@
- # 2) modpost is then used to
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
-+# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
- # 5) compile all <module>.mod.c files
- # 6) final link of the module to a <module.ko> file
-
-@@ -41,6 +42,10 @@ include scripts/Makefile.lib
-
- kernelsymfile := $(objtree)/Module.symvers
- modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
-+kernelmarkersfile := $(objtree)/Module.markers
-+modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
-+
-+markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
-
- # Step 1), find all modules listed in $(MODVERDIR)/
- __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
-@@ -58,16 +63,27 @@ quiet_cmd_modpost = MODPOST
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
-+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
-+ $(if $(CONFIG_MARKERS),-M $(markersfile)) \
- $(filter-out FORCE,$^)
-
- PHONY += __modpost
- __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
- $(call cmd,modpost)
-
-+quiet_cmd_kernel-mod = MODPOST $@
-+ cmd_kernel-mod = $(cmd_modpost) $@
-+
-+vmlinux.o: FORCE
-+ $(call cmd,kernel-mod)
-+
- # Declare generated files as targets for modpost
- $(symverfile): __modpost ;
- $(modules:.ko=.mod.c): __modpost ;
-
-+ifdef CONFIG_MARKERS
-+$(markersfile): __modpost ;
-+endif
-
- # Step 5), compile all *.mod.c files
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 0ec3321..383f310 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -10,7 +10,8 @@
- *
- * Usage: modpost vmlinux module1.o module2.o ...
- */
--
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <ctype.h>
- #include "modpost.h"
- #include "../../include/linux/license.h"
-@@ -385,6 +386,8 @@ static void parse_elf(struct elf_info *info, const char *filename)
- info->export_unused_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
- info->export_gpl_future_sec = i;
-+ else if (strcmp(secname, "__markers_strings") == 0)
-+ info->markers_strings_sec = i;
-
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
-@@ -900,6 +903,62 @@ static void check_sec_ref(struct module *mod, const char *modname,
- }
- }
-
-+static void get_markers(struct elf_info *info, struct module *mod)
-+{
-+ const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-+ const char *strings = (const char *) info->hdr + sh->sh_offset;
-+ const Elf_Sym *sym, *first_sym, *last_sym;
-+ size_t n;
-+
-+ if (!info->markers_strings_sec)
-+ return;
-+
-+ /*
-+ * First count the strings. We look for all the symbols defined
-+ * in the __markers_strings section named __mstrtab_*. For
-+ * these local names, the compiler puts a random .NNN suffix on,
-+ * so the names don't correspond exactly.
-+ */
-+ first_sym = last_sym = NULL;
-+ n = 0;
-+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ if (first_sym == NULL)
-+ first_sym = sym;
-+ last_sym = sym;
-+ ++n;
-+ }
-+
-+ if (n == 0)
-+ return;
-+
-+ /*
-+ * Now collect each name and format into a line for the output.
-+ * Lines look like:
-+ * marker_name vmlinux marker %s format %d
-+ * The format string after the second \t can use whitespace.
-+ */
-+ mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-+ mod->nmarkers = n;
-+
-+ n = 0;
-+ for (sym = first_sym; sym <= last_sym; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ const char *name = strings + sym->st_value;
-+ const char *fmt = strchr(name, '\0') + 1;
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+ mod->markers[n++] = line;
-+ }
-+}
-+
- /**
- * Functions used only during module init is marked __init and is stored in
- * a .init.text section. Likewise data is marked __initdata and stored in
-@@ -1103,6 +1162,8 @@ static void read_symbols(char *modname)
- get_src_version(modname, mod->srcversion,
- sizeof(mod->srcversion)-1);
-
-+ get_markers(&info, mod);
-+
- parse_elf_finish(&info);
-
- /* Our trick to get versioning for struct_module - it's
-@@ -1436,6 +1497,93 @@ static void write_dump(const char *fname)
- write_if_changed(&buf, fname);
- }
-
-+static void add_marker(struct module *mod, const char *name, const char *fmt)
-+{
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+
-+ mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-+ sizeof mod->markers[0])));
-+ mod->markers[mod->nmarkers++] = line;
-+}
-+
-+static void read_markers(const char *fname)
-+{
-+ unsigned long size, pos = 0;
-+ void *file = grab_file(fname, &size);
-+ char *line;
-+
-+ if (!file) /* No old markers, silently ignore */
-+ return;
-+
-+ while ((line = get_next_line(&pos, file, size))) {
-+ char *marker, *modname, *fmt;
-+ struct module *mod;
-+
-+ marker = line;
-+ modname = strchr(marker, '\t');
-+ if (!modname)
-+ goto fail;
-+ *modname++ = '\0';
-+ fmt = strchr(modname, '\t');
-+ if (!fmt)
-+ goto fail;
-+ *fmt++ = '\0';
-+ if (*marker == '\0' || *modname == '\0')
-+ goto fail;
-+
-+ mod = find_module(modname);
-+ if (!mod) {
-+ if (is_vmlinux(modname))
-+ have_vmlinux = 1;
-+ mod = new_module(NOFAIL(strdup(modname)));
-+ mod->skip = 1;
-+ }
-+
-+ add_marker(mod, marker, fmt);
-+ }
-+ return;
-+fail:
-+ fatal("parse error in markers list file\n");
-+}
-+
-+static int compare_strings(const void *a, const void *b)
-+{
-+ return strcmp(*(const char **) a, *(const char **) b);
-+}
-+
-+static void write_markers(const char *fname)
-+{
-+ struct buffer buf = { };
-+ struct module *mod;
-+ size_t i;
-+
-+ for (mod = modules; mod; mod = mod->next)
-+ if ((!external_module || !mod->skip) && mod->markers != NULL) {
-+ /*
-+ * Sort the strings so we can skip duplicates when
-+ * we write them out.
-+ */
-+ qsort(mod->markers, mod->nmarkers,
-+ sizeof mod->markers[0], &compare_strings);
-+ for (i = 0; i < mod->nmarkers; ++i) {
-+ char *line = mod->markers[i];
-+ buf_write(&buf, line, strlen(line));
-+ while (i + 1 < mod->nmarkers &&
-+ !strcmp(mod->markers[i],
-+ mod->markers[i + 1]))
-+ free(mod->markers[i++]);
-+ free(mod->markers[i]);
-+ }
-+ free(mod->markers);
-+ mod->markers = NULL;
-+ }
-+
-+ write_if_changed(&buf, fname);
-+}
-+
-+
- int main(int argc, char **argv)
- {
- struct module *mod;
-@@ -1444,8 +1592,10 @@ int main(int argc, char **argv)
- char *kernel_read = NULL, *module_read = NULL;
- char *dump_write = NULL;
- int opt;
-+ char *markers_read = NULL;
-+ char *markers_write = NULL;
-
-- while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
-+ while ((opt = getopt(argc, argv, "i:I:mo:aM:K:")) != -1) {
- switch(opt) {
- case 'i':
- kernel_read = optarg;
-@@ -1463,6 +1613,12 @@ int main(int argc, char **argv)
- case 'a':
- all_versions = 1;
- break;
-+ case 'M':
-+ markers_write = optarg;
-+ break;
-+ case 'K':
-+ markers_read = optarg;
-+ break;
- default:
- exit(1);
- }
-@@ -1502,5 +1658,11 @@ int main(int argc, char **argv)
- if (dump_write)
- write_dump(dump_write);
-
-+ if (markers_read)
-+ read_markers(markers_read);
-+
-+ if (markers_write)
-+ write_markers(markers_write);
-+
- return 0;
- }
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index d398c61..27b05e6 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -107,6 +107,8 @@ struct module {
- int has_init;
- int has_cleanup;
- struct buffer dev_table_buf;
-+ char **markers;
-+ size_t nmarkers;
- char srcversion[25];
- };
-
-@@ -121,6 +123,7 @@ struct elf_info {
- Elf_Section export_gpl_sec;
- Elf_Section export_unused_gpl_sec;
- Elf_Section export_gpl_future_sec;
-+ Elf_Section markers_strings_sec;
- const char *strtab;
- char *modinfo;
- unsigned int modinfo_len;
Deleted: trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u4.patch
===================================================================
--- trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u4.patch 2008-07-04 02:18:23 UTC (rev 6)
+++ trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u4.patch 2008-07-04 02:22:00 UTC (rev 7)
@@ -1,1917 +0,0 @@
-diff --git a/Makefile b/Makefile
-index ce04b1f..f059302 100644
---- a/Makefile
-+++ b/Makefile
-@@ -581,7 +581,7 @@ quiet_cmd_vmlinux__ ?= LD $@
- cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
- --start-group $(vmlinux-main) --end-group \
-- $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
-+ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
-
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN .version
-@@ -686,10 +686,30 @@ $(KALLSYMS): scripts ;
-
- endif # ifdef CONFIG_KALLSYMS
-
-+# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
-+# relevant sections renamed as per the linker script.
-+quiet_cmd_vmlinux-modpost = LD $@
-+ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
-+ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
-+ $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
-+define rule_vmlinux-modpost
-+ :
-+ +$(call cmd,vmlinux-modpost)
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
-+ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
-+endef
-+
-+
- # vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
-+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
-+ $(call vmlinux-modpost)
- $(call if_changed_rule,vmlinux__)
-
-+# build vmlinux.o first to catch section mismatch errors early
-+$(kallsyms.o): vmlinux.o
-+vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
-+ $(call if_changed_rule,vmlinux-modpost)
-+
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
-index cf069b7..d39d5c5 100644
---- a/arch/i386/Kconfig.debug
-+++ b/arch/i386/Kconfig.debug
-@@ -29,6 +29,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
-index d6cc9c0..7bbda2e 100644
---- a/arch/i386/kernel/vmlinux.lds.S
-+++ b/arch/i386/kernel/vmlinux.lds.S
-@@ -52,6 +52,7 @@ SECTIONS
- /* writeable */
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
-index 2782b48..17d4a44 100644
---- a/arch/ia64/Kconfig.debug
-+++ b/arch/ia64/Kconfig.debug
-@@ -12,6 +12,12 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-
- choice
- prompt "Physical memory granularity"
-diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
-index a676e79..c6ea47e 100644
---- a/arch/ia64/kernel/vmlinux.lds.S
-+++ b/arch/ia64/kernel/vmlinux.lds.S
-@@ -193,7 +193,7 @@ SECTIONS
-
- data : { } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET)
-- { *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
-+ { *(.data) *(.data1) *(.gnu.linkonce.d*) MARKER CONSTRUCTORS }
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET)
-diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
-index 860472a..5c3a9f5 100644
---- a/arch/ppc64/Kconfig.debug
-+++ b/arch/ppc64/Kconfig.debug
-@@ -16,6 +16,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
-index 4103cc1..76d0bf0 100644
---- a/arch/ppc64/kernel/vmlinux.lds.S
-+++ b/arch/ppc64/kernel/vmlinux.lds.S
-@@ -118,6 +118,7 @@ SECTIONS
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
-+ MARKER
- }
-
- .opd : {
-diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
-index cd8d39f..f39bf8d 100644
---- a/arch/sparc64/Kconfig.debug
-+++ b/arch/sparc64/Kconfig.debug
-@@ -21,6 +21,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_DCFLUSH
- bool "D-cache flush debugging"
- depends on DEBUG_KERNEL
-diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
-index a710d38..d4b3b62 100644
---- a/arch/sparc64/kernel/vmlinux.lds.S
-+++ b/arch/sparc64/kernel/vmlinux.lds.S
-@@ -27,6 +27,7 @@ SECTIONS
- .data :
- {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
-diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
-index cb33186..d0260cb 100644
---- a/arch/x86_64/Kconfig.debug
-+++ b/arch/x86_64/Kconfig.debug
-@@ -55,6 +55,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config IOMMU_LEAK
- bool "IOMMU leak tracing"
- depends on DEBUG_KERNEL
-diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
-index f656f19..12ce116 100644
---- a/arch/x86_64/kernel/vmlinux.lds.S
-+++ b/arch/x86_64/kernel/vmlinux.lds.S
-@@ -33,6 +33,7 @@ SECTIONS
-
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 54fb0a0..cbdcd93 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -158,7 +158,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
- // ================= 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);
-@@ -171,8 +171,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast);
- 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);
-
-
- /////////////////////////////////////////////////////////////////////////////////
-@@ -945,12 +945,13 @@ static int ad_lacpdu_send(struct port *port)
- * 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);
-@@ -965,7 +966,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
- skb->nh.raw = skb->data + 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
-@@ -1762,7 +1763,7 @@ static void ad_disable_collecting_distributing(struct port *port)
- */
- 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
-@@ -1795,13 +1796,14 @@ static void ad_marker_info_send(struct port *port)
- * @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
-@@ -1820,7 +1822,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
- * 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
-@@ -2208,15 +2211,16 @@ void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 leng
- 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:
-diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
-index 4119f0f..7e770ff 100644
---- a/drivers/net/bonding/bond_3ad.h
-+++ b/drivers/net/bonding/bond_3ad.h
-@@ -105,7 +105,8 @@ 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 {
-@@ -161,7 +162,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)
-@@ -174,12 +175,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()
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index bb340cb..fd6e57f 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -6,10 +6,18 @@
- #define VMLINUX_SYMBOL(_sym_) _sym_
- #endif
-
-+/* Kernel markers : pointers */
-+#define MARKER \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__start___markers) = .; \
-+ *(__markers) \
-+ VMLINUX_SYMBOL(__stop___markers) = .;
-+
- #define RODATA \
- .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
-+ *(__markers_strings) /* Markers: strings */ \
- } \
- \
- .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
-diff --git a/include/linux/marker.h b/include/linux/marker.h
-new file mode 100644
-index 0000000..efbc82b
---- /dev/null
-+++ b/include/linux/marker.h
-@@ -0,0 +1,139 @@
-+#ifndef _LINUX_MARKER_H
-+#define _LINUX_MARKER_H
-+
-+/*
-+ * Code markup for dynamic and static tracing.
-+ *
-+ * See Documentation/marker.txt.
-+ *
-+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
-+ *
-+ * This file is released under the GPLv2.
-+ * See the file COPYING for more details.
-+ */
-+
-+#include <linux/types.h>
-+
-+struct module;
-+struct marker;
-+
-+/**
-+ * marker_probe_func - Type of a marker probe function
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @fmt: format string
-+ * @args: variable argument list pointer. Use a pointer to overcome C's
-+ * inability to pass this around as a pointer in a portable manner in
-+ * the callee otherwise.
-+ *
-+ * 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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args);
-+
-+struct marker_probe_closure {
-+ marker_probe_func *func; /* Callback */
-+ void *probe_private; /* Private probe data */
-+};
-+
-+struct marker {
-+ const char *name; /* Marker name */
-+ const char *format; /* Marker format string, describing the
-+ * variable argument list.
-+ */
-+ char state; /* Marker state. */
-+ char ptype; /* probe type : 0 : single, 1 : multi */
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+} __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_private, format, args...) \
-+ do { \
-+ static const char __mstrtab_##name[] \
-+ __attribute__((section("__markers_strings"))) \
-+ = #name "\0" format; \
-+ static struct marker __mark_##name \
-+ __attribute__((section("__markers"), aligned(8))) = \
-+ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
-+ 0, 0, marker_probe_cb, \
-+ { __mark_empty_function, NULL}, NULL }; \
-+ __mark_check_format(format, ## args); \
-+ if (unlikely(__mark_##name.state)) { \
-+ (*__mark_##name.call) \
-+ (&__mark_##name, call_private, \
-+ format, ## args); \
-+ } \
-+ } while (0)
-+
-+extern void marker_update_probe_range(struct marker *begin,
-+ struct marker *end);
-+#else /* !CONFIG_MARKERS */
-+#define __trace_mark(name, call_private, format, args...) \
-+ __mark_check_format(format, ## args)
-+static inline void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{ }
-+#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)
-+
-+/**
-+ * 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 __attribute__ ((format (printf, 1, 2))) __mark_check_format(const char *fmt, ...)
-+{
-+}
-+
-+extern marker_probe_func __mark_empty_function;
-+
-+extern void marker_probe_cb(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+extern void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+
-+/*
-+ * 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 *probe_private);
-+
-+/*
-+ * Returns the private data given to marker_probe_register.
-+ */
-+extern int marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private);
-+/*
-+ * Unregister a marker by providing the registered private data.
-+ */
-+extern int marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private);
-+
-+extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
-+ int num);
-+
-+#endif
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 8da8948..2ad5efd 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -18,6 +18,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>
-@@ -328,6 +329,10 @@ struct module
- /* The command line arguments (may be mangled). People like
- keeping pointers to this stuff */
- char *args;
-+#ifdef CONFIG_MARKERS
-+ struct marker *markers;
-+ unsigned int num_markers;
-+#endif
- };
-
- /* FIXME: It'd be nice to isolate modules during init, too, so they
-@@ -448,6 +453,7 @@ int register_module_notifier(struct notifier_block * nb);
- int unregister_module_notifier(struct notifier_block * nb);
-
- extern void print_modules(void);
-+extern void module_update_markers(void);
- #else /* !CONFIG_MODULES... */
- #define EXPORT_SYMBOL(sym)
- #define EXPORT_SYMBOL_GPL(sym)
-@@ -537,6 +543,10 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
- static inline void print_modules(void)
- {
- }
-+
-+static inline void module_update_markers(void)
-+{
-+}
- #endif /* CONFIG_MODULES */
-
- #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
-diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
-index 91057d6..bcd0acb 100644
---- a/include/linux/rcupdate.h
-+++ b/include/linux/rcupdate.h
-@@ -42,6 +42,19 @@
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
-
-+/*
-+ * Prevent the compiler from merging or refetching accesses. The compiler
-+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
-+ * but only when the compiler is aware of some particular ordering. One way
-+ * to make the compiler aware of ordering is to put the two invocations of
-+ * ACCESS_ONCE() in different C statements.
-+ *
-+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
-+ * merging, or refetching absolutely anything at any time.
-+ *
-+ */
-+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-+
- /**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
-@@ -102,6 +115,7 @@ struct rcu_data {
- struct rcu_head *donelist;
- struct rcu_head **donetail;
- int cpu;
-+ struct rcu_head barrier;
- };
-
- DECLARE_PER_CPU(struct rcu_data, rcu_data);
-@@ -266,6 +280,6 @@ extern void FASTCALL(call_rcu(struct rcu_head *head,
- extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
- void (*func)(struct rcu_head *head)));
- extern void synchronize_kernel(void);
--
-+extern void rcu_barrier(void);
- #endif /* __KERNEL__ */
- #endif /* __LINUX_RCUPDATE_H */
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 0b8c8ca..f8248bc 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_AUDIT) += audit.o
- obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
- obj-$(CONFIG_AUDITFILESYSTEM) += auditfs.o
- obj-$(CONFIG_KPROBES) += kprobes.o
-+obj-$(CONFIG_MARKERS) += marker.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
-diff --git a/kernel/marker.c b/kernel/marker.c
-new file mode 100644
-index 0000000..c4c2cd8
---- /dev/null
-+++ b/kernel/marker.c
-@@ -0,0 +1,851 @@
-+/*
-+ * 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 marker __start___markers[];
-+extern struct marker __stop___markers[];
-+
-+/* Set to 1 to enable marker debug output */
-+const int marker_debug;
-+
-+/*
-+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
-+ * and module markers and the hash table.
-+ */
-+static DEFINE_MUTEX(markers_mutex);
-+
-+/*
-+ * Marker hash table, containing the active markers.
-+ * Protected by module_mutex.
-+ */
-+#define MARKER_HASH_BITS 6
-+#define MARKER_TABLE_SIZE (1 << MARKER_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 marker. It is
-+ * also used to delay the free of multiple probes array until a quiescent state
-+ * is reached.
-+ * marker entries modifications are protected by the markers_mutex.
-+ */
-+struct marker_entry {
-+ struct hlist_node hlist;
-+ char *format;
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+ int refcount; /* Number of times armed. 0 if disarmed. */
-+ struct rcu_head rcu;
-+ void *oldptr;
-+ char rcu_pending:1;
-+ char ptype:1;
-+ char name[0]; /* Contains name'\0'format'\0' */
-+};
-+
-+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
-+
-+/**
-+ * __mark_empty_function - Empty probe callback
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args)
-+{
-+}
-+EXPORT_SYMBOL_GPL(__mark_empty_function);
-+
-+/*
-+ * marker_probe_cb Callback that prepares the variable argument list for probes.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Since we do not use "typical" pointer based RCU in the 1 argument case, we
-+ * need to put a full smp_rmb() in this branch. This is why we do not use
-+ * rcu_dereference() for the pointer read.
-+ */
-+void marker_probe_cb(const struct marker *mdata, void *call_private,
-+ const char *fmt, ...)
-+{
-+ va_list args;
-+ char ptype;
-+
-+ /*
-+ * disabling preemption to make sure the teardown of the callbacks can
-+ * be done correctly when they are in modules and they insure RCU read
-+ * coherency.
-+ */
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ va_start(args, fmt);
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ va_end(args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++) {
-+ va_start(args, fmt);
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ va_end(args);
-+ }
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb);
-+
-+/*
-+ * marker_probe_cb Callback that does not prepare the variable argument list.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Should be connected to markers "MARK_NOARGS".
-+ */
-+void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...)
-+{
-+ va_list args; /* not initialized */
-+ char ptype;
-+
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++)
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
-+
-+static void free_old_closure(struct rcu_head *head)
-+{
-+ struct marker_entry *entry = container_of(head,
-+ struct marker_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 marker_entry *entry)
-+{
-+ int i;
-+
-+ if (!marker_debug)
-+ return;
-+
-+ if (!entry->ptype) {
-+ printk(KERN_DEBUG "Single probe : %p %p\n",
-+ entry->single.func,
-+ entry->single.probe_private);
-+ } else {
-+ 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 marker_probe_closure *
-+marker_entry_add_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0;
-+ struct marker_probe_closure *old, *new;
-+
-+ WARN_ON(!probe);
-+
-+ debug_print_probes(entry);
-+ old = entry->multi;
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe &&
-+ entry->single.probe_private == probe_private)
-+ return ERR_PTR(-EBUSY);
-+ if (entry->single.func == __mark_empty_function) {
-+ /* 0 -> 1 probes */
-+ entry->single.func = probe;
-+ entry->single.probe_private = probe_private;
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* 1 -> 2 probes */
-+ nr_probes = 1;
-+ old = NULL;
-+ }
-+ } else {
-+ /* (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 marker_probe_closure),
-+ GFP_KERNEL);
-+ if (new == NULL)
-+ return ERR_PTR(-ENOMEM);
-+ if (!old)
-+ new[0] = entry->single;
-+ else
-+ memcpy(new, old,
-+ nr_probes * sizeof(struct marker_probe_closure));
-+ new[nr_probes].func = probe;
-+ new[nr_probes].probe_private = probe_private;
-+ entry->refcount = nr_probes + 1;
-+ entry->multi = new;
-+ entry->ptype = 1;
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+static struct marker_probe_closure *
-+marker_entry_remove_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0, nr_del = 0, i;
-+ struct marker_probe_closure *old, *new;
-+
-+ old = entry->multi;
-+
-+ debug_print_probes(entry);
-+ if (!entry->ptype) {
-+ /* 0 -> N is an error */
-+ WARN_ON(entry->single.func == __mark_empty_function);
-+ /* 1 -> 0 probes */
-+ WARN_ON(probe && entry->single.func != probe);
-+ WARN_ON(entry->single.probe_private != probe_private);
-+ entry->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* (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->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ } else if (nr_probes - nr_del == 1) {
-+ /* N -> 1, (N > 1) */
-+ for (i = 0; old[i].func; i++)
-+ if ((probe && old[i].func != probe) ||
-+ old[i].probe_private != probe_private)
-+ entry->single = old[i];
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ } else {
-+ int j = 0;
-+ /* N -> M, (N > 1, M > 1) */
-+ /* + 1 for NULL */
-+ new = kzalloc((nr_probes - nr_del + 1)
-+ * sizeof(struct marker_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->ptype = 1;
-+ entry->multi = new;
-+ }
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+/*
-+ * 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 struct marker_entry *add_marker(const char *name, const char *format)
-+{
-+ 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\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 marker_entry) + name_len + format_len,
-+ GFP_KERNEL);
-+ if (!e)
-+ return ERR_PTR(-ENOMEM);
-+ memcpy(&e->name[0], name, name_len);
-+ if (format) {
-+ e->format = &e->name[name_len];
-+ memcpy(e->format, format, format_len);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ trace_mark(core_marker_format, "name %s format %s",
-+ e->name, e->format);
-+ } else {
-+ e->format = NULL;
-+ e->call = marker_probe_cb;
-+ }
-+ e->single.func = __mark_empty_function;
-+ e->single.probe_private = NULL;
-+ e->multi = NULL;
-+ e->ptype = 0;
-+ e->refcount = 0;
-+ e->rcu_pending = 0;
-+ hlist_add_head(&e->hlist, head);
-+ return e;
-+}
-+
-+/*
-+ * Remove the marker from the marker hash table. Must be called with mutex_lock
-+ * held.
-+ */
-+static int 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;
-+ 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)
-+ return -ENOENT;
-+ if (e->single.func != __mark_empty_function)
-+ return -EBUSY;
-+ hlist_del(&e->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if (e->rcu_pending)
-+ rcu_barrier();
-+ kfree(e);
-+ return 0;
-+}
-+
-+/*
-+ * 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);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ e->single = (*entry)->single;
-+ e->multi = (*entry)->multi;
-+ e->ptype = (*entry)->ptype;
-+ e->refcount = (*entry)->refcount;
-+ e->rcu_pending = 0;
-+ hlist_add_before(&e->hlist, &(*entry)->hlist);
-+ hlist_del(&(*entry)->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if ((*entry)->rcu_pending)
-+ rcu_barrier();
-+ 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 marker *elem,
-+ int active)
-+{
-+ 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;
-+ }
-+
-+ /*
-+ * probe_cb setup (statically known) is done here. It is
-+ * asynchronous with the rest of execution, therefore we only
-+ * pass from a "safe" callback (with argument) to an "unsafe"
-+ * callback (does not set arguments).
-+ */
-+ elem->call = (*entry)->call;
-+ /*
-+ * Sanity check :
-+ * We only update the single probe private data when the ptr is
-+ * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
-+ */
-+ WARN_ON(elem->single.func != __mark_empty_function
-+ && elem->single.probe_private
-+ != (*entry)->single.probe_private &&
-+ !elem->ptype);
-+ elem->single.probe_private = (*entry)->single.probe_private;
-+ /*
-+ * Make sure the private data is valid when we update the
-+ * single probe ptr.
-+ */
-+ smp_wmb();
-+ elem->single.func = (*entry)->single.func;
-+ /*
-+ * 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);
-+ /*
-+ * Update the function or multi probe array pointer before setting the
-+ * ptype.
-+ */
-+ smp_wmb();
-+ elem->ptype = (*entry)->ptype;
-+ elem->state = active;
-+
-+ 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 marker *elem)
-+{
-+ /* leave "call" as is. It is known statically. */
-+ elem->state = 0;
-+ elem->single.func = __mark_empty_function;
-+ /* Update the function before setting the ptype */
-+ smp_wmb();
-+ elem->ptype = 0; /* single probe */
-+ /*
-+ * 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
-+ *
-+ * Updates the probe callback corresponding to a range of markers.
-+ */
-+void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{
-+ struct marker *iter;
-+ struct marker_entry *mark_entry;
-+
-+ mutex_lock(&markers_mutex);
-+ for (iter = begin; iter < end; iter++) {
-+ mark_entry = get_marker(iter->name);
-+ if (mark_entry) {
-+ set_marker(&mark_entry, iter,
-+ !!mark_entry->refcount);
-+ /*
-+ * ignore error, continue
-+ */
-+ } else {
-+ disable_marker(iter);
-+ }
-+ }
-+ mutex_unlock(&markers_mutex);
-+}
-+
-+/*
-+ * 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.
-+ *
-+ * Internal callback only changed before the first probe is connected to it.
-+ * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
-+ * transitions. All other transitions will leave the old private data valid.
-+ * This makes the non-atomicity of the callback/private data updates valid.
-+ *
-+ * "special case" updates :
-+ * 0 -> 1 callback
-+ * 1 -> 0 callback
-+ * 1 -> 2 callbacks
-+ * 2 -> 1 callbacks
-+ * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
-+ * Site effect : marker_set_format may delete the marker entry (creating a
-+ * replacement).
-+ */
-+static void marker_update_probes(void)
-+{
-+ /* Core kernel markers */
-+ marker_update_probe_range(__start___markers, __stop___markers);
-+ /* Markers in modules. */
-+ module_update_markers();
-+}
-+
-+/**
-+ * marker_probe_register - Connect a probe to a marker
-+ * @name: marker name
-+ * @format: format string
-+ * @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 marker_probe_register(const char *name, const char *format,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ entry = add_marker(name, format);
-+ if (IS_ERR(entry)) {
-+ ret = PTR_ERR(entry);
-+ goto end;
-+ }
-+ }
-+ /*
-+ * If we detect that a call_rcu is pending for this marker,
-+ * make sure it's executed now.
-+ */
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_add_probe(entry, probe, probe_private);
-+ if (IS_ERR(old)) {
-+ ret = PTR_ERR(old);
-+ goto end;
-+ }
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_register);
-+
-+/**
-+ * marker_probe_unregister - Disconnect a probe from a marker
-+ * @name: marker name
-+ * @probe: probe function pointer
-+ * @probe_private: probe private data
-+ *
-+ * Returns the private data given to marker_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 marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ struct marker_probe_closure *old;
-+ int ret = 0;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, probe, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister);
-+
-+static struct marker_entry *
-+get_marker_from_private_data(marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ unsigned int i;
-+ struct hlist_head *head;
-+ struct hlist_node *node;
-+
-+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-+ head = &marker_table[i];
-+ hlist_for_each_entry(entry, node, head, hlist) {
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe
-+ && entry->single.probe_private
-+ == probe_private)
-+ return entry;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ closure = entry->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func == probe &&
-+ closure[i].probe_private
-+ == probe_private)
-+ return entry;
-+ }
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
-+ * @probe: probe function
-+ * @probe_private: probe private data
-+ *
-+ * Unregister a probe by providing the registered private data.
-+ * Only removes the first marker found in hash table.
-+ * Return 0 on success or error value.
-+ * 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 marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, NULL, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(entry->name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
-+
-+/**
-+ * marker_get_private_data - Get a marker's probe private data
-+ * @name: marker name
-+ * @probe: probe to match
-+ * @num: get the nth matching probe's private data
-+ *
-+ * Returns the nth private data pointer (starting from 0) matching, or an
-+ * ERR_PTR.
-+ * 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, marker_probe_func *probe,
-+ int num)
-+{
-+ 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 i;
-+
-+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
-+ hlist_for_each_entry(e, node, head, hlist) {
-+ if (!strcmp(name, e->name)) {
-+ if (!e->ptype) {
-+ if (num == 0 && e->single.func == probe)
-+ return e->single.probe_private;
-+ else
-+ break;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ int match = 0;
-+ closure = e->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func != probe)
-+ continue;
-+ if (match++ == num)
-+ return closure[i].probe_private;
-+ }
-+ }
-+ }
-+ }
-+ return ERR_PTR(-ENOENT);
-+}
-+EXPORT_SYMBOL_GPL(marker_get_private_data);
-diff --git a/kernel/module.c b/kernel/module.c
-index 18b39bc..096c3dc 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1504,6 +1504,8 @@ static struct module *load_module(void __user *umod,
- void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
- struct exception_table_entry *extable;
- int gpgsig_ok;
-+ unsigned int markersindex;
-+ unsigned int markersstringsindex;
-
- DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
- umod, len, uargs);
-@@ -1734,6 +1736,9 @@ static struct module *load_module(void __user *umod,
- tainted |= 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++) {
-@@ -1757,6 +1762,12 @@ static struct module *load_module(void __user *umod,
- goto cleanup;
- }
-
-+#ifdef CONFIG_MARKERS
-+ mod->markers = (void *)sechdrs[markersindex].sh_addr;
-+ mod->num_markers =
-+ sechdrs[markersindex].sh_size / sizeof(*mod->markers);
-+#endif
-+
- /* Set up and sort exception table */
- mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
- mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
-@@ -1768,6 +1779,12 @@ static struct module *load_module(void __user *umod,
-
- add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-
-+#ifdef CONFIG_MARKERS
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+#endif
-+
- err = module_finalize(hdr, sechdrs, mod);
- if (err < 0)
- goto cleanup;
-@@ -2175,6 +2192,20 @@ void struct_module(struct module *mod) { return; }
- EXPORT_SYMBOL(struct_module);
- #endif
-
-+#ifdef CONFIG_MARKERS
-+void module_update_markers(void)
-+{
-+ struct module *mod;
-+
-+ down(&module_mutex);
-+ list_for_each_entry(mod, &modules, list)
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+ up(&module_mutex);
-+}
-+#endif
-+
- static int __init modules_init(void)
- {
- return subsystem_register(&module_subsys);
-diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
-index 1b16bfc..20ade31 100644
---- a/kernel/rcupdate.c
-+++ b/kernel/rcupdate.c
-@@ -46,6 +46,7 @@
- #include <linux/notifier.h>
- #include <linux/rcupdate.h>
- #include <linux/cpu.h>
-+#include <linux/mutex.h>
-
- /* Definition for rcupdate control block. */
- struct rcu_ctrlblk rcu_ctrlblk =
-@@ -98,6 +99,10 @@ void fastcall call_rcu(struct rcu_head *head,
- local_irq_restore(flags);
- }
-
-+static atomic_t rcu_barrier_cpu_count;
-+static DEFINE_MUTEX(rcu_barrier_mutex);
-+static struct completion rcu_barrier_completion;
-+
- /**
- * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
- * @head: structure to be used for queueing the RCU updates.
-@@ -410,6 +415,44 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
- return NOTIFY_OK;
- }
-
-+static void rcu_barrier_callback(struct rcu_head *notused)
-+{
-+ if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-+ complete(&rcu_barrier_completion);
-+}
-+
-+/*
-+ * Called with preemption disabled, and from cross-cpu IRQ context.
-+ */
-+static void rcu_barrier_func(void *notused)
-+{
-+ int cpu = smp_processor_id();
-+ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
-+ struct rcu_head *head;
-+
-+ head = &rdp->barrier;
-+ atomic_inc(&rcu_barrier_cpu_count);
-+ call_rcu(head, rcu_barrier_callback);
-+}
-+
-+/**
-+ * rcu_barrier - Wait until all the in-flight RCUs are complete.
-+ */
-+void rcu_barrier(void)
-+{
-+ BUG_ON(in_interrupt());
-+ /* Take cpucontrol mutex to protect against CPU hotplug */
-+ mutex_lock(&rcu_barrier_mutex);
-+ init_completion(&rcu_barrier_completion);
-+ atomic_set(&rcu_barrier_cpu_count, 0);
-+ on_each_cpu(rcu_barrier_func, NULL, 0, 1);
-+ wait_for_completion(&rcu_barrier_completion);
-+ mutex_unlock(&rcu_barrier_mutex);
-+}
-+EXPORT_SYMBOL_GPL(rcu_barrier);
-+
-+
-+
- static struct notifier_block __devinitdata rcu_nb = {
- .notifier_call = rcu_cpu_notify,
- };
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index b3d31b5..b100a32 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -13,6 +13,7 @@
- # 2) modpost is then used to
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
-+# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
- # 5) compile all <module>.mod.c files
- # 6) final link of the module to a <module.ko> file
-
-@@ -40,6 +41,11 @@ include scripts/Makefile.lib
-
- symverfile := $(objtree)/Module.symvers
-
-+kernelmarkersfile := $(objtree)/Module.markers
-+modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
-+
-+markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
-+
- # Step 1), find all modules listed in $(MODVERDIR)/
- __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
- modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
-@@ -53,16 +59,27 @@ quiet_cmd_modpost = MODPOST
- cmd_modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
-+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
-+ $(if $(CONFIG_MARKERS),-M $(markersfile)) \
- $(filter-out FORCE,$^)
-
- .PHONY: __modpost
- __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
- $(call cmd,modpost)
-
-+quiet_cmd_kernel-mod = MODPOST $@
-+ cmd_kernel-mod = $(cmd_modpost) $@
-+
-+vmlinux.o: FORCE
-+ $(call cmd,kernel-mod)
-+
- # Declare generated files as targets for modpost
- $(symverfile): __modpost ;
- $(modules:.ko=.mod.c): __modpost ;
-
-+ifdef CONFIG_MARKERS
-+$(markersfile): __modpost ;
-+endif
-
- # Step 5), compile all *.mod.c files
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 2a174e5..c25948c 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -10,7 +10,8 @@
- *
- * Usage: modpost vmlinux module1.o module2.o ...
- */
--
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <ctype.h>
- #include "modpost.h"
-
-@@ -289,7 +290,9 @@ parse_elf(struct elf_info *info, const char *filename)
- if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
- info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
- info->modinfo_len = sechdrs[i].sh_size;
-- }
-+ } else if (strcmp(secstrings+sechdrs[i].sh_name, "__markers_strings") == 0)
-+ info->markers_strings_sec = i;
-+
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
-
-@@ -397,6 +400,63 @@ is_vmlinux(const char *modname)
- return strcmp(myname, "vmlinux") == 0;
- }
-
-+static void get_markers(struct elf_info *info, struct module *mod)
-+{
-+ const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-+ const char *strings = (const char *) info->hdr + sh->sh_offset;
-+ const Elf_Sym *sym, *first_sym, *last_sym;
-+ size_t n;
-+
-+
-+ if (!info->markers_strings_sec)
-+ return;
-+
-+ /*
-+ * First count the strings. We look for all the symbols defined
-+ * in the __markers_strings section named __mstrtab_*. For
-+ * these local names, the compiler puts a random .NNN suffix on,
-+ * so the names don't correspond exactly.
-+ */
-+ first_sym = last_sym = NULL;
-+ n = 0;
-+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ if (first_sym == NULL)
-+ first_sym = sym;
-+ last_sym = sym;
-+ ++n;
-+ }
-+
-+ if (n == 0)
-+ return;
-+ /*
-+ * Now collect each name and format into a line for the output.
-+ * Lines look like:
-+ * marker_name vmlinux marker %s format %d
-+ * The format string after the second \t can use whitespace.
-+ */
-+ mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-+ mod->nmarkers = n;
-+
-+ n = 0;
-+ for (sym = first_sym; sym <= last_sym; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ const char *name = strings + sym->st_value;
-+ const char *fmt = strchr(name, '\0') + 1;
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+ mod->markers[n++] = line;
-+ }
-+}
-+
-+
- void
- read_symbols(char *modname)
- {
-@@ -426,6 +486,7 @@ read_symbols(char *modname)
- }
- maybe_frob_version(modname, info.modinfo, info.modinfo_len,
- (void *)info.modinfo - (void *)info.hdr);
-+ get_markers(&info, mod);
- parse_elf_finish(&info);
-
- /* Our trick to get versioning for struct_module - it's
-@@ -682,6 +743,92 @@ write_dump(const char *fname)
- write_if_changed(&buf, fname);
- }
-
-+static void add_marker(struct module *mod, const char *name, const char *fmt)
-+{
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+
-+ mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-+ sizeof mod->markers[0])));
-+ mod->markers[mod->nmarkers++] = line;
-+}
-+
-+static void read_markers(const char *fname)
-+{
-+ unsigned long size, pos = 0;
-+ void *file = grab_file(fname, &size);
-+ char *line;
-+
-+ if (!file) /* No old markers, silently ignore */
-+ return;
-+
-+ while ((line = get_next_line(&pos, file, size))) {
-+ char *marker, *modname, *fmt;
-+ struct module *mod;
-+
-+ marker = line;
-+ modname = strchr(marker, '\t');
-+ if (!modname)
-+ goto fail;
-+ *modname++ = '\0';
-+ fmt = strchr(modname, '\t');
-+ if (!fmt)
-+ goto fail;
-+ *fmt++ = '\0';
-+ if (*marker == '\0' || *modname == '\0')
-+ goto fail;
-+
-+ mod = find_module(modname);
-+ if (!mod) {
-+ if (is_vmlinux(modname))
-+ have_vmlinux = 1;
-+ mod = new_module(NOFAIL(strdup(modname)));
-+ mod->skip = 1;
-+ }
-+
-+ add_marker(mod, marker, fmt);
-+ }
-+ return;
-+fail:
-+ fatal("parse error in markers list file\n");
-+}
-+
-+static int compare_strings(const void *a, const void *b)
-+{
-+ return strcmp(*(const char **) a, *(const char **) b);
-+}
-+
-+static void write_markers(const char *fname)
-+{
-+ struct buffer buf = { };
-+ struct module *mod;
-+ size_t i;
-+
-+ for (mod = modules; mod; mod = mod->next)
-+ if (mod->markers != NULL) {
-+ /*
-+ * Sort the strings so we can skip duplicates when
-+ * we write them out.
-+ */
-+ qsort(mod->markers, mod->nmarkers,
-+ sizeof mod->markers[0], &compare_strings);
-+ for (i = 0; i < mod->nmarkers; ++i) {
-+ char *line = mod->markers[i];
-+ buf_write(&buf, line, strlen(line));
-+ while (i + 1 < mod->nmarkers &&
-+ !strcmp(mod->markers[i],
-+ mod->markers[i + 1]))
-+ free(mod->markers[i++]);
-+ free(mod->markers[i]);
-+ }
-+ free(mod->markers);
-+ mod->markers = NULL;
-+ }
-+
-+ write_if_changed(&buf, fname);
-+}
-+
- int
- main(int argc, char **argv)
- {
-@@ -690,8 +837,10 @@ main(int argc, char **argv)
- char fname[SZ];
- char *dump_read = NULL, *dump_write = NULL;
- int opt;
-+ char *markers_read = NULL;
-+ char *markers_write = NULL;
-
-- while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
-+ while ((opt = getopt(argc, argv, "i:mo:M:K:")) != -1) {
- switch(opt) {
- case 'i':
- dump_read = optarg;
-@@ -702,6 +851,12 @@ main(int argc, char **argv)
- case 'o':
- dump_write = optarg;
- break;
-+ case 'M':
-+ markers_write = optarg;
-+ break;
-+ case 'K':
-+ markers_read = optarg;
-+ break;
- default:
- exit(1);
- }
-@@ -732,6 +887,12 @@ main(int argc, char **argv)
- if (dump_write)
- write_dump(dump_write);
-
-+ if (markers_read)
-+ read_markers(markers_read);
-+
-+ if (markers_write)
-+ write_markers(markers_write);
-+
- return 0;
- }
-
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index 4871343..d79d7ea 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -18,6 +18,7 @@
- #define Elf_Sym Elf32_Sym
- #define ELF_ST_BIND ELF32_ST_BIND
- #define ELF_ST_TYPE ELF32_ST_TYPE
-+#define Elf_Section Elf32_Half
-
- #else
-
-@@ -26,7 +27,7 @@
- #define Elf_Sym Elf64_Sym
- #define ELF_ST_BIND ELF64_ST_BIND
- #define ELF_ST_TYPE ELF64_ST_TYPE
--
-+#define Elf_Section Elf64_Half
- #endif
-
- #if KERNEL_ELFDATA != HOST_ELFDATA
-@@ -77,6 +78,8 @@ struct module {
- int has_init;
- int has_cleanup;
- struct buffer dev_table_buf;
-+ char **markers;
-+ size_t nmarkers;
- };
-
- struct elf_info {
-@@ -85,6 +88,7 @@ struct elf_info {
- Elf_Shdr *sechdrs;
- Elf_Sym *symtab_start;
- Elf_Sym *symtab_stop;
-+ Elf_Section markers_strings_sec;
- const char *strtab;
- char *modinfo;
- unsigned int modinfo_len;
Deleted: trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u5.patch
===================================================================
--- trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u5.patch 2008-07-04 02:18:23 UTC (rev 6)
+++ trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u5.patch 2008-07-04 02:22:00 UTC (rev 7)
@@ -1,1917 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 5bfc101..d495f16 100644
---- a/Makefile
-+++ b/Makefile
-@@ -583,7 +583,7 @@ quiet_cmd_vmlinux__ ?= LD $@
- cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
- --start-group $(vmlinux-main) --end-group \
-- $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
-+ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
-
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN .version
-@@ -688,10 +688,30 @@ $(KALLSYMS): scripts ;
-
- endif # ifdef CONFIG_KALLSYMS
-
-+# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
-+# relevant sections renamed as per the linker script.
-+quiet_cmd_vmlinux-modpost = LD $@
-+ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
-+ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
-+ $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
-+define rule_vmlinux-modpost
-+ :
-+ +$(call cmd,vmlinux-modpost)
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
-+ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
-+endef
-+
-+
- # vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
-+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
-+ $(call vmlinux-modpost)
- $(call if_changed_rule,vmlinux__)
-
-+# build vmlinux.o first to catch section mismatch errors early
-+$(kallsyms.o): vmlinux.o
-+vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
-+ $(call if_changed_rule,vmlinux-modpost)
-+
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
-index cf069b7..d39d5c5 100644
---- a/arch/i386/Kconfig.debug
-+++ b/arch/i386/Kconfig.debug
-@@ -29,6 +29,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
-index e8db99c..b846b21 100644
---- a/arch/i386/kernel/vmlinux.lds.S
-+++ b/arch/i386/kernel/vmlinux.lds.S
-@@ -53,6 +53,7 @@ SECTIONS
- /* writeable */
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
-index 2782b48..17d4a44 100644
---- a/arch/ia64/Kconfig.debug
-+++ b/arch/ia64/Kconfig.debug
-@@ -12,6 +12,12 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-
- choice
- prompt "Physical memory granularity"
-diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
-index a676e79..c6ea47e 100644
---- a/arch/ia64/kernel/vmlinux.lds.S
-+++ b/arch/ia64/kernel/vmlinux.lds.S
-@@ -193,7 +193,7 @@ SECTIONS
-
- data : { } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET)
-- { *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
-+ { *(.data) *(.data1) *(.gnu.linkonce.d*) MARKER CONSTRUCTORS }
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET)
-diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
-index 860472a..5c3a9f5 100644
---- a/arch/ppc64/Kconfig.debug
-+++ b/arch/ppc64/Kconfig.debug
-@@ -16,6 +16,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
-index 4103cc1..76d0bf0 100644
---- a/arch/ppc64/kernel/vmlinux.lds.S
-+++ b/arch/ppc64/kernel/vmlinux.lds.S
-@@ -118,6 +118,7 @@ SECTIONS
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
-+ MARKER
- }
-
- .opd : {
-diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
-index cd8d39f..f39bf8d 100644
---- a/arch/sparc64/Kconfig.debug
-+++ b/arch/sparc64/Kconfig.debug
-@@ -21,6 +21,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_DCFLUSH
- bool "D-cache flush debugging"
- depends on DEBUG_KERNEL
-diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
-index a710d38..d4b3b62 100644
---- a/arch/sparc64/kernel/vmlinux.lds.S
-+++ b/arch/sparc64/kernel/vmlinux.lds.S
-@@ -27,6 +27,7 @@ SECTIONS
- .data :
- {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
-diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
-index cb33186..d0260cb 100644
---- a/arch/x86_64/Kconfig.debug
-+++ b/arch/x86_64/Kconfig.debug
-@@ -55,6 +55,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config IOMMU_LEAK
- bool "IOMMU leak tracing"
- depends on DEBUG_KERNEL
-diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
-index 053c826..3b3928f 100644
---- a/arch/x86_64/kernel/vmlinux.lds.S
-+++ b/arch/x86_64/kernel/vmlinux.lds.S
-@@ -33,6 +33,7 @@ SECTIONS
-
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 181f3d2..c7c5dc6 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -158,7 +158,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
- // ================= 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);
-@@ -171,8 +171,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast);
- 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);
-
-
- /////////////////////////////////////////////////////////////////////////////////
-@@ -945,12 +945,13 @@ static int ad_lacpdu_send(struct port *port)
- * 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);
-@@ -965,7 +966,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
- skb->nh.raw = skb->data + 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
-@@ -1762,7 +1763,7 @@ static void ad_disable_collecting_distributing(struct port *port)
- */
- 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
-@@ -1795,13 +1796,14 @@ static void ad_marker_info_send(struct port *port)
- * @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
-@@ -1820,7 +1822,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
- * 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
-@@ -2208,15 +2211,16 @@ void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 leng
- 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:
-diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
-index 4c60b17..2bb477e 100644
---- a/drivers/net/bonding/bond_3ad.h
-+++ b/drivers/net/bonding/bond_3ad.h
-@@ -105,7 +105,8 @@ 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 {
-@@ -161,7 +162,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)
-@@ -174,12 +175,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()
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index bb340cb..fd6e57f 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -6,10 +6,18 @@
- #define VMLINUX_SYMBOL(_sym_) _sym_
- #endif
-
-+/* Kernel markers : pointers */
-+#define MARKER \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__start___markers) = .; \
-+ *(__markers) \
-+ VMLINUX_SYMBOL(__stop___markers) = .;
-+
- #define RODATA \
- .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
-+ *(__markers_strings) /* Markers: strings */ \
- } \
- \
- .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
-diff --git a/include/linux/marker.h b/include/linux/marker.h
-new file mode 100644
-index 0000000..efbc82b
---- /dev/null
-+++ b/include/linux/marker.h
-@@ -0,0 +1,139 @@
-+#ifndef _LINUX_MARKER_H
-+#define _LINUX_MARKER_H
-+
-+/*
-+ * Code markup for dynamic and static tracing.
-+ *
-+ * See Documentation/marker.txt.
-+ *
-+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
-+ *
-+ * This file is released under the GPLv2.
-+ * See the file COPYING for more details.
-+ */
-+
-+#include <linux/types.h>
-+
-+struct module;
-+struct marker;
-+
-+/**
-+ * marker_probe_func - Type of a marker probe function
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @fmt: format string
-+ * @args: variable argument list pointer. Use a pointer to overcome C's
-+ * inability to pass this around as a pointer in a portable manner in
-+ * the callee otherwise.
-+ *
-+ * 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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args);
-+
-+struct marker_probe_closure {
-+ marker_probe_func *func; /* Callback */
-+ void *probe_private; /* Private probe data */
-+};
-+
-+struct marker {
-+ const char *name; /* Marker name */
-+ const char *format; /* Marker format string, describing the
-+ * variable argument list.
-+ */
-+ char state; /* Marker state. */
-+ char ptype; /* probe type : 0 : single, 1 : multi */
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+} __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_private, format, args...) \
-+ do { \
-+ static const char __mstrtab_##name[] \
-+ __attribute__((section("__markers_strings"))) \
-+ = #name "\0" format; \
-+ static struct marker __mark_##name \
-+ __attribute__((section("__markers"), aligned(8))) = \
-+ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
-+ 0, 0, marker_probe_cb, \
-+ { __mark_empty_function, NULL}, NULL }; \
-+ __mark_check_format(format, ## args); \
-+ if (unlikely(__mark_##name.state)) { \
-+ (*__mark_##name.call) \
-+ (&__mark_##name, call_private, \
-+ format, ## args); \
-+ } \
-+ } while (0)
-+
-+extern void marker_update_probe_range(struct marker *begin,
-+ struct marker *end);
-+#else /* !CONFIG_MARKERS */
-+#define __trace_mark(name, call_private, format, args...) \
-+ __mark_check_format(format, ## args)
-+static inline void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{ }
-+#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)
-+
-+/**
-+ * 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 __attribute__ ((format (printf, 1, 2))) __mark_check_format(const char *fmt, ...)
-+{
-+}
-+
-+extern marker_probe_func __mark_empty_function;
-+
-+extern void marker_probe_cb(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+extern void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+
-+/*
-+ * 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 *probe_private);
-+
-+/*
-+ * Returns the private data given to marker_probe_register.
-+ */
-+extern int marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private);
-+/*
-+ * Unregister a marker by providing the registered private data.
-+ */
-+extern int marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private);
-+
-+extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
-+ int num);
-+
-+#endif
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 8da8948..2ad5efd 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -18,6 +18,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>
-@@ -328,6 +329,10 @@ struct module
- /* The command line arguments (may be mangled). People like
- keeping pointers to this stuff */
- char *args;
-+#ifdef CONFIG_MARKERS
-+ struct marker *markers;
-+ unsigned int num_markers;
-+#endif
- };
-
- /* FIXME: It'd be nice to isolate modules during init, too, so they
-@@ -448,6 +453,7 @@ int register_module_notifier(struct notifier_block * nb);
- int unregister_module_notifier(struct notifier_block * nb);
-
- extern void print_modules(void);
-+extern void module_update_markers(void);
- #else /* !CONFIG_MODULES... */
- #define EXPORT_SYMBOL(sym)
- #define EXPORT_SYMBOL_GPL(sym)
-@@ -537,6 +543,10 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
- static inline void print_modules(void)
- {
- }
-+
-+static inline void module_update_markers(void)
-+{
-+}
- #endif /* CONFIG_MODULES */
-
- #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
-diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
-index 91057d6..bcd0acb 100644
---- a/include/linux/rcupdate.h
-+++ b/include/linux/rcupdate.h
-@@ -42,6 +42,19 @@
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
-
-+/*
-+ * Prevent the compiler from merging or refetching accesses. The compiler
-+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
-+ * but only when the compiler is aware of some particular ordering. One way
-+ * to make the compiler aware of ordering is to put the two invocations of
-+ * ACCESS_ONCE() in different C statements.
-+ *
-+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
-+ * merging, or refetching absolutely anything at any time.
-+ *
-+ */
-+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-+
- /**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
-@@ -102,6 +115,7 @@ struct rcu_data {
- struct rcu_head *donelist;
- struct rcu_head **donetail;
- int cpu;
-+ struct rcu_head barrier;
- };
-
- DECLARE_PER_CPU(struct rcu_data, rcu_data);
-@@ -266,6 +280,6 @@ extern void FASTCALL(call_rcu(struct rcu_head *head,
- extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
- void (*func)(struct rcu_head *head)));
- extern void synchronize_kernel(void);
--
-+extern void rcu_barrier(void);
- #endif /* __KERNEL__ */
- #endif /* __LINUX_RCUPDATE_H */
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 0b8c8ca..f8248bc 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_AUDIT) += audit.o
- obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
- obj-$(CONFIG_AUDITFILESYSTEM) += auditfs.o
- obj-$(CONFIG_KPROBES) += kprobes.o
-+obj-$(CONFIG_MARKERS) += marker.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
-diff --git a/kernel/marker.c b/kernel/marker.c
-new file mode 100644
-index 0000000..c4c2cd8
---- /dev/null
-+++ b/kernel/marker.c
-@@ -0,0 +1,851 @@
-+/*
-+ * 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 marker __start___markers[];
-+extern struct marker __stop___markers[];
-+
-+/* Set to 1 to enable marker debug output */
-+const int marker_debug;
-+
-+/*
-+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
-+ * and module markers and the hash table.
-+ */
-+static DEFINE_MUTEX(markers_mutex);
-+
-+/*
-+ * Marker hash table, containing the active markers.
-+ * Protected by module_mutex.
-+ */
-+#define MARKER_HASH_BITS 6
-+#define MARKER_TABLE_SIZE (1 << MARKER_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 marker. It is
-+ * also used to delay the free of multiple probes array until a quiescent state
-+ * is reached.
-+ * marker entries modifications are protected by the markers_mutex.
-+ */
-+struct marker_entry {
-+ struct hlist_node hlist;
-+ char *format;
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+ int refcount; /* Number of times armed. 0 if disarmed. */
-+ struct rcu_head rcu;
-+ void *oldptr;
-+ char rcu_pending:1;
-+ char ptype:1;
-+ char name[0]; /* Contains name'\0'format'\0' */
-+};
-+
-+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
-+
-+/**
-+ * __mark_empty_function - Empty probe callback
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args)
-+{
-+}
-+EXPORT_SYMBOL_GPL(__mark_empty_function);
-+
-+/*
-+ * marker_probe_cb Callback that prepares the variable argument list for probes.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Since we do not use "typical" pointer based RCU in the 1 argument case, we
-+ * need to put a full smp_rmb() in this branch. This is why we do not use
-+ * rcu_dereference() for the pointer read.
-+ */
-+void marker_probe_cb(const struct marker *mdata, void *call_private,
-+ const char *fmt, ...)
-+{
-+ va_list args;
-+ char ptype;
-+
-+ /*
-+ * disabling preemption to make sure the teardown of the callbacks can
-+ * be done correctly when they are in modules and they insure RCU read
-+ * coherency.
-+ */
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ va_start(args, fmt);
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ va_end(args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++) {
-+ va_start(args, fmt);
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ va_end(args);
-+ }
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb);
-+
-+/*
-+ * marker_probe_cb Callback that does not prepare the variable argument list.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Should be connected to markers "MARK_NOARGS".
-+ */
-+void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...)
-+{
-+ va_list args; /* not initialized */
-+ char ptype;
-+
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++)
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
-+
-+static void free_old_closure(struct rcu_head *head)
-+{
-+ struct marker_entry *entry = container_of(head,
-+ struct marker_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 marker_entry *entry)
-+{
-+ int i;
-+
-+ if (!marker_debug)
-+ return;
-+
-+ if (!entry->ptype) {
-+ printk(KERN_DEBUG "Single probe : %p %p\n",
-+ entry->single.func,
-+ entry->single.probe_private);
-+ } else {
-+ 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 marker_probe_closure *
-+marker_entry_add_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0;
-+ struct marker_probe_closure *old, *new;
-+
-+ WARN_ON(!probe);
-+
-+ debug_print_probes(entry);
-+ old = entry->multi;
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe &&
-+ entry->single.probe_private == probe_private)
-+ return ERR_PTR(-EBUSY);
-+ if (entry->single.func == __mark_empty_function) {
-+ /* 0 -> 1 probes */
-+ entry->single.func = probe;
-+ entry->single.probe_private = probe_private;
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* 1 -> 2 probes */
-+ nr_probes = 1;
-+ old = NULL;
-+ }
-+ } else {
-+ /* (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 marker_probe_closure),
-+ GFP_KERNEL);
-+ if (new == NULL)
-+ return ERR_PTR(-ENOMEM);
-+ if (!old)
-+ new[0] = entry->single;
-+ else
-+ memcpy(new, old,
-+ nr_probes * sizeof(struct marker_probe_closure));
-+ new[nr_probes].func = probe;
-+ new[nr_probes].probe_private = probe_private;
-+ entry->refcount = nr_probes + 1;
-+ entry->multi = new;
-+ entry->ptype = 1;
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+static struct marker_probe_closure *
-+marker_entry_remove_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0, nr_del = 0, i;
-+ struct marker_probe_closure *old, *new;
-+
-+ old = entry->multi;
-+
-+ debug_print_probes(entry);
-+ if (!entry->ptype) {
-+ /* 0 -> N is an error */
-+ WARN_ON(entry->single.func == __mark_empty_function);
-+ /* 1 -> 0 probes */
-+ WARN_ON(probe && entry->single.func != probe);
-+ WARN_ON(entry->single.probe_private != probe_private);
-+ entry->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* (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->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ } else if (nr_probes - nr_del == 1) {
-+ /* N -> 1, (N > 1) */
-+ for (i = 0; old[i].func; i++)
-+ if ((probe && old[i].func != probe) ||
-+ old[i].probe_private != probe_private)
-+ entry->single = old[i];
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ } else {
-+ int j = 0;
-+ /* N -> M, (N > 1, M > 1) */
-+ /* + 1 for NULL */
-+ new = kzalloc((nr_probes - nr_del + 1)
-+ * sizeof(struct marker_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->ptype = 1;
-+ entry->multi = new;
-+ }
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+/*
-+ * 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 struct marker_entry *add_marker(const char *name, const char *format)
-+{
-+ 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\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 marker_entry) + name_len + format_len,
-+ GFP_KERNEL);
-+ if (!e)
-+ return ERR_PTR(-ENOMEM);
-+ memcpy(&e->name[0], name, name_len);
-+ if (format) {
-+ e->format = &e->name[name_len];
-+ memcpy(e->format, format, format_len);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ trace_mark(core_marker_format, "name %s format %s",
-+ e->name, e->format);
-+ } else {
-+ e->format = NULL;
-+ e->call = marker_probe_cb;
-+ }
-+ e->single.func = __mark_empty_function;
-+ e->single.probe_private = NULL;
-+ e->multi = NULL;
-+ e->ptype = 0;
-+ e->refcount = 0;
-+ e->rcu_pending = 0;
-+ hlist_add_head(&e->hlist, head);
-+ return e;
-+}
-+
-+/*
-+ * Remove the marker from the marker hash table. Must be called with mutex_lock
-+ * held.
-+ */
-+static int 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;
-+ 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)
-+ return -ENOENT;
-+ if (e->single.func != __mark_empty_function)
-+ return -EBUSY;
-+ hlist_del(&e->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if (e->rcu_pending)
-+ rcu_barrier();
-+ kfree(e);
-+ return 0;
-+}
-+
-+/*
-+ * 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);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ e->single = (*entry)->single;
-+ e->multi = (*entry)->multi;
-+ e->ptype = (*entry)->ptype;
-+ e->refcount = (*entry)->refcount;
-+ e->rcu_pending = 0;
-+ hlist_add_before(&e->hlist, &(*entry)->hlist);
-+ hlist_del(&(*entry)->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if ((*entry)->rcu_pending)
-+ rcu_barrier();
-+ 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 marker *elem,
-+ int active)
-+{
-+ 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;
-+ }
-+
-+ /*
-+ * probe_cb setup (statically known) is done here. It is
-+ * asynchronous with the rest of execution, therefore we only
-+ * pass from a "safe" callback (with argument) to an "unsafe"
-+ * callback (does not set arguments).
-+ */
-+ elem->call = (*entry)->call;
-+ /*
-+ * Sanity check :
-+ * We only update the single probe private data when the ptr is
-+ * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
-+ */
-+ WARN_ON(elem->single.func != __mark_empty_function
-+ && elem->single.probe_private
-+ != (*entry)->single.probe_private &&
-+ !elem->ptype);
-+ elem->single.probe_private = (*entry)->single.probe_private;
-+ /*
-+ * Make sure the private data is valid when we update the
-+ * single probe ptr.
-+ */
-+ smp_wmb();
-+ elem->single.func = (*entry)->single.func;
-+ /*
-+ * 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);
-+ /*
-+ * Update the function or multi probe array pointer before setting the
-+ * ptype.
-+ */
-+ smp_wmb();
-+ elem->ptype = (*entry)->ptype;
-+ elem->state = active;
-+
-+ 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 marker *elem)
-+{
-+ /* leave "call" as is. It is known statically. */
-+ elem->state = 0;
-+ elem->single.func = __mark_empty_function;
-+ /* Update the function before setting the ptype */
-+ smp_wmb();
-+ elem->ptype = 0; /* single probe */
-+ /*
-+ * 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
-+ *
-+ * Updates the probe callback corresponding to a range of markers.
-+ */
-+void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{
-+ struct marker *iter;
-+ struct marker_entry *mark_entry;
-+
-+ mutex_lock(&markers_mutex);
-+ for (iter = begin; iter < end; iter++) {
-+ mark_entry = get_marker(iter->name);
-+ if (mark_entry) {
-+ set_marker(&mark_entry, iter,
-+ !!mark_entry->refcount);
-+ /*
-+ * ignore error, continue
-+ */
-+ } else {
-+ disable_marker(iter);
-+ }
-+ }
-+ mutex_unlock(&markers_mutex);
-+}
-+
-+/*
-+ * 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.
-+ *
-+ * Internal callback only changed before the first probe is connected to it.
-+ * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
-+ * transitions. All other transitions will leave the old private data valid.
-+ * This makes the non-atomicity of the callback/private data updates valid.
-+ *
-+ * "special case" updates :
-+ * 0 -> 1 callback
-+ * 1 -> 0 callback
-+ * 1 -> 2 callbacks
-+ * 2 -> 1 callbacks
-+ * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
-+ * Site effect : marker_set_format may delete the marker entry (creating a
-+ * replacement).
-+ */
-+static void marker_update_probes(void)
-+{
-+ /* Core kernel markers */
-+ marker_update_probe_range(__start___markers, __stop___markers);
-+ /* Markers in modules. */
-+ module_update_markers();
-+}
-+
-+/**
-+ * marker_probe_register - Connect a probe to a marker
-+ * @name: marker name
-+ * @format: format string
-+ * @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 marker_probe_register(const char *name, const char *format,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ entry = add_marker(name, format);
-+ if (IS_ERR(entry)) {
-+ ret = PTR_ERR(entry);
-+ goto end;
-+ }
-+ }
-+ /*
-+ * If we detect that a call_rcu is pending for this marker,
-+ * make sure it's executed now.
-+ */
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_add_probe(entry, probe, probe_private);
-+ if (IS_ERR(old)) {
-+ ret = PTR_ERR(old);
-+ goto end;
-+ }
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_register);
-+
-+/**
-+ * marker_probe_unregister - Disconnect a probe from a marker
-+ * @name: marker name
-+ * @probe: probe function pointer
-+ * @probe_private: probe private data
-+ *
-+ * Returns the private data given to marker_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 marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ struct marker_probe_closure *old;
-+ int ret = 0;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, probe, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister);
-+
-+static struct marker_entry *
-+get_marker_from_private_data(marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ unsigned int i;
-+ struct hlist_head *head;
-+ struct hlist_node *node;
-+
-+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-+ head = &marker_table[i];
-+ hlist_for_each_entry(entry, node, head, hlist) {
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe
-+ && entry->single.probe_private
-+ == probe_private)
-+ return entry;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ closure = entry->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func == probe &&
-+ closure[i].probe_private
-+ == probe_private)
-+ return entry;
-+ }
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
-+ * @probe: probe function
-+ * @probe_private: probe private data
-+ *
-+ * Unregister a probe by providing the registered private data.
-+ * Only removes the first marker found in hash table.
-+ * Return 0 on success or error value.
-+ * 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 marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, NULL, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(entry->name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
-+
-+/**
-+ * marker_get_private_data - Get a marker's probe private data
-+ * @name: marker name
-+ * @probe: probe to match
-+ * @num: get the nth matching probe's private data
-+ *
-+ * Returns the nth private data pointer (starting from 0) matching, or an
-+ * ERR_PTR.
-+ * 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, marker_probe_func *probe,
-+ int num)
-+{
-+ 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 i;
-+
-+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
-+ hlist_for_each_entry(e, node, head, hlist) {
-+ if (!strcmp(name, e->name)) {
-+ if (!e->ptype) {
-+ if (num == 0 && e->single.func == probe)
-+ return e->single.probe_private;
-+ else
-+ break;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ int match = 0;
-+ closure = e->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func != probe)
-+ continue;
-+ if (match++ == num)
-+ return closure[i].probe_private;
-+ }
-+ }
-+ }
-+ }
-+ return ERR_PTR(-ENOENT);
-+}
-+EXPORT_SYMBOL_GPL(marker_get_private_data);
-diff --git a/kernel/module.c b/kernel/module.c
-index 7f0ccd8..1cd4c54 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1505,6 +1505,8 @@ static struct module *load_module(void __user *umod,
- struct exception_table_entry *extable;
- mm_segment_t old_fs;
- int gpgsig_ok;
-+ unsigned int markersindex;
-+ unsigned int markersstringsindex;
-
- DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
- umod, len, uargs);
-@@ -1735,6 +1737,9 @@ static struct module *load_module(void __user *umod,
- tainted |= 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++) {
-@@ -1758,6 +1763,12 @@ static struct module *load_module(void __user *umod,
- goto cleanup;
- }
-
-+#ifdef CONFIG_MARKERS
-+ mod->markers = (void *)sechdrs[markersindex].sh_addr;
-+ mod->num_markers =
-+ sechdrs[markersindex].sh_size / sizeof(*mod->markers);
-+#endif
-+
- /* Set up and sort exception table */
- mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
- mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
-@@ -1769,6 +1780,12 @@ static struct module *load_module(void __user *umod,
-
- add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-
-+#ifdef CONFIG_MARKERS
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+#endif
-+
- err = module_finalize(hdr, sechdrs, mod);
- if (err < 0)
- goto cleanup;
-@@ -2186,6 +2203,20 @@ void struct_module(struct module *mod) { return; }
- EXPORT_SYMBOL(struct_module);
- #endif
-
-+#ifdef CONFIG_MARKERS
-+void module_update_markers(void)
-+{
-+ struct module *mod;
-+
-+ down(&module_mutex);
-+ list_for_each_entry(mod, &modules, list)
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+ up(&module_mutex);
-+}
-+#endif
-+
- static int __init modules_init(void)
- {
- return subsystem_register(&module_subsys);
-diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
-index 1b16bfc..20ade31 100644
---- a/kernel/rcupdate.c
-+++ b/kernel/rcupdate.c
-@@ -46,6 +46,7 @@
- #include <linux/notifier.h>
- #include <linux/rcupdate.h>
- #include <linux/cpu.h>
-+#include <linux/mutex.h>
-
- /* Definition for rcupdate control block. */
- struct rcu_ctrlblk rcu_ctrlblk =
-@@ -98,6 +99,10 @@ void fastcall call_rcu(struct rcu_head *head,
- local_irq_restore(flags);
- }
-
-+static atomic_t rcu_barrier_cpu_count;
-+static DEFINE_MUTEX(rcu_barrier_mutex);
-+static struct completion rcu_barrier_completion;
-+
- /**
- * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
- * @head: structure to be used for queueing the RCU updates.
-@@ -410,6 +415,44 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
- return NOTIFY_OK;
- }
-
-+static void rcu_barrier_callback(struct rcu_head *notused)
-+{
-+ if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-+ complete(&rcu_barrier_completion);
-+}
-+
-+/*
-+ * Called with preemption disabled, and from cross-cpu IRQ context.
-+ */
-+static void rcu_barrier_func(void *notused)
-+{
-+ int cpu = smp_processor_id();
-+ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
-+ struct rcu_head *head;
-+
-+ head = &rdp->barrier;
-+ atomic_inc(&rcu_barrier_cpu_count);
-+ call_rcu(head, rcu_barrier_callback);
-+}
-+
-+/**
-+ * rcu_barrier - Wait until all the in-flight RCUs are complete.
-+ */
-+void rcu_barrier(void)
-+{
-+ BUG_ON(in_interrupt());
-+ /* Take cpucontrol mutex to protect against CPU hotplug */
-+ mutex_lock(&rcu_barrier_mutex);
-+ init_completion(&rcu_barrier_completion);
-+ atomic_set(&rcu_barrier_cpu_count, 0);
-+ on_each_cpu(rcu_barrier_func, NULL, 0, 1);
-+ wait_for_completion(&rcu_barrier_completion);
-+ mutex_unlock(&rcu_barrier_mutex);
-+}
-+EXPORT_SYMBOL_GPL(rcu_barrier);
-+
-+
-+
- static struct notifier_block __devinitdata rcu_nb = {
- .notifier_call = rcu_cpu_notify,
- };
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index b3d31b5..b100a32 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -13,6 +13,7 @@
- # 2) modpost is then used to
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
-+# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
- # 5) compile all <module>.mod.c files
- # 6) final link of the module to a <module.ko> file
-
-@@ -40,6 +41,11 @@ include scripts/Makefile.lib
-
- symverfile := $(objtree)/Module.symvers
-
-+kernelmarkersfile := $(objtree)/Module.markers
-+modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
-+
-+markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
-+
- # Step 1), find all modules listed in $(MODVERDIR)/
- __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
- modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
-@@ -53,16 +59,27 @@ quiet_cmd_modpost = MODPOST
- cmd_modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
-+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
-+ $(if $(CONFIG_MARKERS),-M $(markersfile)) \
- $(filter-out FORCE,$^)
-
- .PHONY: __modpost
- __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
- $(call cmd,modpost)
-
-+quiet_cmd_kernel-mod = MODPOST $@
-+ cmd_kernel-mod = $(cmd_modpost) $@
-+
-+vmlinux.o: FORCE
-+ $(call cmd,kernel-mod)
-+
- # Declare generated files as targets for modpost
- $(symverfile): __modpost ;
- $(modules:.ko=.mod.c): __modpost ;
-
-+ifdef CONFIG_MARKERS
-+$(markersfile): __modpost ;
-+endif
-
- # Step 5), compile all *.mod.c files
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 2a174e5..c25948c 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -10,7 +10,8 @@
- *
- * Usage: modpost vmlinux module1.o module2.o ...
- */
--
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <ctype.h>
- #include "modpost.h"
-
-@@ -289,7 +290,9 @@ parse_elf(struct elf_info *info, const char *filename)
- if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
- info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
- info->modinfo_len = sechdrs[i].sh_size;
-- }
-+ } else if (strcmp(secstrings+sechdrs[i].sh_name, "__markers_strings") == 0)
-+ info->markers_strings_sec = i;
-+
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
-
-@@ -397,6 +400,63 @@ is_vmlinux(const char *modname)
- return strcmp(myname, "vmlinux") == 0;
- }
-
-+static void get_markers(struct elf_info *info, struct module *mod)
-+{
-+ const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-+ const char *strings = (const char *) info->hdr + sh->sh_offset;
-+ const Elf_Sym *sym, *first_sym, *last_sym;
-+ size_t n;
-+
-+
-+ if (!info->markers_strings_sec)
-+ return;
-+
-+ /*
-+ * First count the strings. We look for all the symbols defined
-+ * in the __markers_strings section named __mstrtab_*. For
-+ * these local names, the compiler puts a random .NNN suffix on,
-+ * so the names don't correspond exactly.
-+ */
-+ first_sym = last_sym = NULL;
-+ n = 0;
-+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ if (first_sym == NULL)
-+ first_sym = sym;
-+ last_sym = sym;
-+ ++n;
-+ }
-+
-+ if (n == 0)
-+ return;
-+ /*
-+ * Now collect each name and format into a line for the output.
-+ * Lines look like:
-+ * marker_name vmlinux marker %s format %d
-+ * The format string after the second \t can use whitespace.
-+ */
-+ mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-+ mod->nmarkers = n;
-+
-+ n = 0;
-+ for (sym = first_sym; sym <= last_sym; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ const char *name = strings + sym->st_value;
-+ const char *fmt = strchr(name, '\0') + 1;
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+ mod->markers[n++] = line;
-+ }
-+}
-+
-+
- void
- read_symbols(char *modname)
- {
-@@ -426,6 +486,7 @@ read_symbols(char *modname)
- }
- maybe_frob_version(modname, info.modinfo, info.modinfo_len,
- (void *)info.modinfo - (void *)info.hdr);
-+ get_markers(&info, mod);
- parse_elf_finish(&info);
-
- /* Our trick to get versioning for struct_module - it's
-@@ -682,6 +743,92 @@ write_dump(const char *fname)
- write_if_changed(&buf, fname);
- }
-
-+static void add_marker(struct module *mod, const char *name, const char *fmt)
-+{
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+
-+ mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-+ sizeof mod->markers[0])));
-+ mod->markers[mod->nmarkers++] = line;
-+}
-+
-+static void read_markers(const char *fname)
-+{
-+ unsigned long size, pos = 0;
-+ void *file = grab_file(fname, &size);
-+ char *line;
-+
-+ if (!file) /* No old markers, silently ignore */
-+ return;
-+
-+ while ((line = get_next_line(&pos, file, size))) {
-+ char *marker, *modname, *fmt;
-+ struct module *mod;
-+
-+ marker = line;
-+ modname = strchr(marker, '\t');
-+ if (!modname)
-+ goto fail;
-+ *modname++ = '\0';
-+ fmt = strchr(modname, '\t');
-+ if (!fmt)
-+ goto fail;
-+ *fmt++ = '\0';
-+ if (*marker == '\0' || *modname == '\0')
-+ goto fail;
-+
-+ mod = find_module(modname);
-+ if (!mod) {
-+ if (is_vmlinux(modname))
-+ have_vmlinux = 1;
-+ mod = new_module(NOFAIL(strdup(modname)));
-+ mod->skip = 1;
-+ }
-+
-+ add_marker(mod, marker, fmt);
-+ }
-+ return;
-+fail:
-+ fatal("parse error in markers list file\n");
-+}
-+
-+static int compare_strings(const void *a, const void *b)
-+{
-+ return strcmp(*(const char **) a, *(const char **) b);
-+}
-+
-+static void write_markers(const char *fname)
-+{
-+ struct buffer buf = { };
-+ struct module *mod;
-+ size_t i;
-+
-+ for (mod = modules; mod; mod = mod->next)
-+ if (mod->markers != NULL) {
-+ /*
-+ * Sort the strings so we can skip duplicates when
-+ * we write them out.
-+ */
-+ qsort(mod->markers, mod->nmarkers,
-+ sizeof mod->markers[0], &compare_strings);
-+ for (i = 0; i < mod->nmarkers; ++i) {
-+ char *line = mod->markers[i];
-+ buf_write(&buf, line, strlen(line));
-+ while (i + 1 < mod->nmarkers &&
-+ !strcmp(mod->markers[i],
-+ mod->markers[i + 1]))
-+ free(mod->markers[i++]);
-+ free(mod->markers[i]);
-+ }
-+ free(mod->markers);
-+ mod->markers = NULL;
-+ }
-+
-+ write_if_changed(&buf, fname);
-+}
-+
- int
- main(int argc, char **argv)
- {
-@@ -690,8 +837,10 @@ main(int argc, char **argv)
- char fname[SZ];
- char *dump_read = NULL, *dump_write = NULL;
- int opt;
-+ char *markers_read = NULL;
-+ char *markers_write = NULL;
-
-- while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
-+ while ((opt = getopt(argc, argv, "i:mo:M:K:")) != -1) {
- switch(opt) {
- case 'i':
- dump_read = optarg;
-@@ -702,6 +851,12 @@ main(int argc, char **argv)
- case 'o':
- dump_write = optarg;
- break;
-+ case 'M':
-+ markers_write = optarg;
-+ break;
-+ case 'K':
-+ markers_read = optarg;
-+ break;
- default:
- exit(1);
- }
-@@ -732,6 +887,12 @@ main(int argc, char **argv)
- if (dump_write)
- write_dump(dump_write);
-
-+ if (markers_read)
-+ read_markers(markers_read);
-+
-+ if (markers_write)
-+ write_markers(markers_write);
-+
- return 0;
- }
-
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index 4871343..d79d7ea 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -18,6 +18,7 @@
- #define Elf_Sym Elf32_Sym
- #define ELF_ST_BIND ELF32_ST_BIND
- #define ELF_ST_TYPE ELF32_ST_TYPE
-+#define Elf_Section Elf32_Half
-
- #else
-
-@@ -26,7 +27,7 @@
- #define Elf_Sym Elf64_Sym
- #define ELF_ST_BIND ELF64_ST_BIND
- #define ELF_ST_TYPE ELF64_ST_TYPE
--
-+#define Elf_Section Elf64_Half
- #endif
-
- #if KERNEL_ELFDATA != HOST_ELFDATA
-@@ -77,6 +78,8 @@ struct module {
- int has_init;
- int has_cleanup;
- struct buffer dev_table_buf;
-+ char **markers;
-+ size_t nmarkers;
- };
-
- struct elf_info {
-@@ -85,6 +88,7 @@ struct elf_info {
- Elf_Shdr *sechdrs;
- Elf_Sym *symtab_start;
- Elf_Sym *symtab_stop;
-+ Elf_Section markers_strings_sec;
- const char *strtab;
- char *modinfo;
- unsigned int modinfo_len;
Deleted: trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u6.patch
===================================================================
--- trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u6.patch 2008-07-04 02:18:23 UTC (rev 6)
+++ trunk/wjhuang/marker_patches/linux-kernel-markers-full-2.6.9.el4u6.patch 2008-07-04 02:22:00 UTC (rev 7)
@@ -1,1917 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 06b517d..afa3d2c 100644
---- a/Makefile
-+++ b/Makefile
-@@ -583,7 +583,7 @@ quiet_cmd_vmlinux__ ?= LD $@
- cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
- --start-group $(vmlinux-main) --end-group \
-- $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
-+ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
-
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN .version
-@@ -688,10 +688,30 @@ $(KALLSYMS): scripts ;
-
- endif # ifdef CONFIG_KALLSYMS
-
-+# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
-+# relevant sections renamed as per the linker script.
-+quiet_cmd_vmlinux-modpost = LD $@
-+ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
-+ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
-+ $(filter-out $(vmlinux-init) $(vmlinux-main) $(vmlinux-lds) FORCE ,$^)
-+define rule_vmlinux-modpost
-+ :
-+ +$(call cmd,vmlinux-modpost)
-+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
-+ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
-+endef
-+
-+
- # vmlinux image - including updated kernel symbols
--vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
-+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
-+ $(call vmlinux-modpost)
- $(call if_changed_rule,vmlinux__)
-
-+# build vmlinux.o first to catch section mismatch errors early
-+$(kallsyms.o): vmlinux.o
-+vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE
-+ $(call if_changed_rule,vmlinux-modpost)
-+
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
-index cf069b7..d39d5c5 100644
---- a/arch/i386/Kconfig.debug
-+++ b/arch/i386/Kconfig.debug
-@@ -29,6 +29,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
-index e8db99c..b846b21 100644
---- a/arch/i386/kernel/vmlinux.lds.S
-+++ b/arch/i386/kernel/vmlinux.lds.S
-@@ -53,6 +53,7 @@ SECTIONS
- /* writeable */
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
-index 2782b48..17d4a44 100644
---- a/arch/ia64/Kconfig.debug
-+++ b/arch/ia64/Kconfig.debug
-@@ -12,6 +12,12 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-
- choice
- prompt "Physical memory granularity"
-diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
-index a676e79..c6ea47e 100644
---- a/arch/ia64/kernel/vmlinux.lds.S
-+++ b/arch/ia64/kernel/vmlinux.lds.S
-@@ -193,7 +193,7 @@ SECTIONS
-
- data : { } :data
- .data : AT(ADDR(.data) - LOAD_OFFSET)
-- { *(.data) *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS }
-+ { *(.data) *(.data1) *(.gnu.linkonce.d*) MARKER CONSTRUCTORS }
-
- . = ALIGN(16); /* gp must be 16-byte aligned for exc. table */
- .got : AT(ADDR(.got) - LOAD_OFFSET)
-diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
-index 860472a..5c3a9f5 100644
---- a/arch/ppc64/Kconfig.debug
-+++ b/arch/ppc64/Kconfig.debug
-@@ -16,6 +16,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_STACK_USAGE
- bool "Stack utilization instrumentation"
- depends on DEBUG_KERNEL
-diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
-index 4103cc1..76d0bf0 100644
---- a/arch/ppc64/kernel/vmlinux.lds.S
-+++ b/arch/ppc64/kernel/vmlinux.lds.S
-@@ -118,6 +118,7 @@ SECTIONS
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
-+ MARKER
- }
-
- .opd : {
-diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
-index cd8d39f..f39bf8d 100644
---- a/arch/sparc64/Kconfig.debug
-+++ b/arch/sparc64/Kconfig.debug
-@@ -21,6 +21,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config DEBUG_DCFLUSH
- bool "D-cache flush debugging"
- depends on DEBUG_KERNEL
-diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
-index a710d38..d4b3b62 100644
---- a/arch/sparc64/kernel/vmlinux.lds.S
-+++ b/arch/sparc64/kernel/vmlinux.lds.S
-@@ -27,6 +27,7 @@ SECTIONS
- .data :
- {
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
- .data1 : { *(.data1) }
-diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
-index cb33186..d0260cb 100644
---- a/arch/x86_64/Kconfig.debug
-+++ b/arch/x86_64/Kconfig.debug
-@@ -55,6 +55,13 @@ config KPROBES
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-+config MARKERS
-+ bool "Activate markers"
-+ default y
-+ help
-+ Place an empty function call at each marker site. Can be
-+ dynamically changed for a probe function.
-+
- config IOMMU_LEAK
- bool "IOMMU leak tracing"
- depends on DEBUG_KERNEL
-diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
-index 053c826..3b3928f 100644
---- a/arch/x86_64/kernel/vmlinux.lds.S
-+++ b/arch/x86_64/kernel/vmlinux.lds.S
-@@ -33,6 +33,7 @@ SECTIONS
-
- .data : { /* Data */
- *(.data)
-+ MARKER
- CONSTRUCTORS
- }
-
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 7a4d28d..991a1ef 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -159,7 +159,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
- // ================= 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);
-@@ -172,8 +172,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast);
- 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);
-
-
- /////////////////////////////////////////////////////////////////////////////////
-@@ -954,12 +954,13 @@ static int ad_lacpdu_send(struct port *port)
- * 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);
-@@ -974,7 +975,7 @@ static int ad_marker_send(struct port *port, struct marker *marker)
- skb->nh.raw = skb->data + 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
-@@ -1771,7 +1772,7 @@ static void ad_disable_collecting_distributing(struct port *port)
- */
- 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
-@@ -1804,13 +1805,14 @@ static void ad_marker_info_send(struct port *port)
- * @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
-@@ -1829,7 +1831,8 @@ static void ad_marker_info_received(struct marker *marker_info,struct port *port
- * 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
-@@ -2217,15 +2220,16 @@ void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 leng
- 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:
-diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
-index 4c60b17..2bb477e 100644
---- a/drivers/net/bonding/bond_3ad.h
-+++ b/drivers/net/bonding/bond_3ad.h
-@@ -105,7 +105,8 @@ 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 {
-@@ -161,7 +162,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)
-@@ -174,12 +175,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()
-
-diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
-index 165a02f..eaf230e 100644
---- a/include/asm-generic/vmlinux.lds.h
-+++ b/include/asm-generic/vmlinux.lds.h
-@@ -6,10 +6,18 @@
- #define VMLINUX_SYMBOL(_sym_) _sym_
- #endif
-
-+/* Kernel markers : pointers */
-+#define MARKER \
-+ . = ALIGN(8); \
-+ VMLINUX_SYMBOL(__start___markers) = .; \
-+ *(__markers) \
-+ VMLINUX_SYMBOL(__stop___markers) = .;
-+
- #define RODATA \
- .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
-+ *(__markers_strings) /* Markers: strings */ \
- } \
- \
- .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
-diff --git a/include/linux/marker.h b/include/linux/marker.h
-new file mode 100644
-index 0000000..efbc82b
---- /dev/null
-+++ b/include/linux/marker.h
-@@ -0,0 +1,139 @@
-+#ifndef _LINUX_MARKER_H
-+#define _LINUX_MARKER_H
-+
-+/*
-+ * Code markup for dynamic and static tracing.
-+ *
-+ * See Documentation/marker.txt.
-+ *
-+ * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
-+ *
-+ * This file is released under the GPLv2.
-+ * See the file COPYING for more details.
-+ */
-+
-+#include <linux/types.h>
-+
-+struct module;
-+struct marker;
-+
-+/**
-+ * marker_probe_func - Type of a marker probe function
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @fmt: format string
-+ * @args: variable argument list pointer. Use a pointer to overcome C's
-+ * inability to pass this around as a pointer in a portable manner in
-+ * the callee otherwise.
-+ *
-+ * 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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args);
-+
-+struct marker_probe_closure {
-+ marker_probe_func *func; /* Callback */
-+ void *probe_private; /* Private probe data */
-+};
-+
-+struct marker {
-+ const char *name; /* Marker name */
-+ const char *format; /* Marker format string, describing the
-+ * variable argument list.
-+ */
-+ char state; /* Marker state. */
-+ char ptype; /* probe type : 0 : single, 1 : multi */
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+} __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_private, format, args...) \
-+ do { \
-+ static const char __mstrtab_##name[] \
-+ __attribute__((section("__markers_strings"))) \
-+ = #name "\0" format; \
-+ static struct marker __mark_##name \
-+ __attribute__((section("__markers"), aligned(8))) = \
-+ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
-+ 0, 0, marker_probe_cb, \
-+ { __mark_empty_function, NULL}, NULL }; \
-+ __mark_check_format(format, ## args); \
-+ if (unlikely(__mark_##name.state)) { \
-+ (*__mark_##name.call) \
-+ (&__mark_##name, call_private, \
-+ format, ## args); \
-+ } \
-+ } while (0)
-+
-+extern void marker_update_probe_range(struct marker *begin,
-+ struct marker *end);
-+#else /* !CONFIG_MARKERS */
-+#define __trace_mark(name, call_private, format, args...) \
-+ __mark_check_format(format, ## args)
-+static inline void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{ }
-+#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)
-+
-+/**
-+ * 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 __attribute__ ((format (printf, 1, 2))) __mark_check_format(const char *fmt, ...)
-+{
-+}
-+
-+extern marker_probe_func __mark_empty_function;
-+
-+extern void marker_probe_cb(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+extern void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...);
-+
-+/*
-+ * 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 *probe_private);
-+
-+/*
-+ * Returns the private data given to marker_probe_register.
-+ */
-+extern int marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private);
-+/*
-+ * Unregister a marker by providing the registered private data.
-+ */
-+extern int marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private);
-+
-+extern void *marker_get_private_data(const char *name, marker_probe_func *probe,
-+ int num);
-+
-+#endif
-diff --git a/include/linux/module.h b/include/linux/module.h
-index 8da8948..2ad5efd 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -18,6 +18,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>
-@@ -328,6 +329,10 @@ struct module
- /* The command line arguments (may be mangled). People like
- keeping pointers to this stuff */
- char *args;
-+#ifdef CONFIG_MARKERS
-+ struct marker *markers;
-+ unsigned int num_markers;
-+#endif
- };
-
- /* FIXME: It'd be nice to isolate modules during init, too, so they
-@@ -448,6 +453,7 @@ int register_module_notifier(struct notifier_block * nb);
- int unregister_module_notifier(struct notifier_block * nb);
-
- extern void print_modules(void);
-+extern void module_update_markers(void);
- #else /* !CONFIG_MODULES... */
- #define EXPORT_SYMBOL(sym)
- #define EXPORT_SYMBOL_GPL(sym)
-@@ -537,6 +543,10 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
- static inline void print_modules(void)
- {
- }
-+
-+static inline void module_update_markers(void)
-+{
-+}
- #endif /* CONFIG_MODULES */
-
- #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
-diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
-index 91057d6..bcd0acb 100644
---- a/include/linux/rcupdate.h
-+++ b/include/linux/rcupdate.h
-@@ -42,6 +42,19 @@
- #include <linux/cpumask.h>
- #include <linux/seqlock.h>
-
-+/*
-+ * Prevent the compiler from merging or refetching accesses. The compiler
-+ * is also forbidden from reordering successive instances of ACCESS_ONCE(),
-+ * but only when the compiler is aware of some particular ordering. One way
-+ * to make the compiler aware of ordering is to put the two invocations of
-+ * ACCESS_ONCE() in different C statements.
-+ *
-+ * This macro does absolutely -nothing- to prevent the CPU from reordering,
-+ * merging, or refetching absolutely anything at any time.
-+ *
-+ */
-+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
-+
- /**
- * struct rcu_head - callback structure for use with RCU
- * @next: next update requests in a list
-@@ -102,6 +115,7 @@ struct rcu_data {
- struct rcu_head *donelist;
- struct rcu_head **donetail;
- int cpu;
-+ struct rcu_head barrier;
- };
-
- DECLARE_PER_CPU(struct rcu_data, rcu_data);
-@@ -266,6 +280,6 @@ extern void FASTCALL(call_rcu(struct rcu_head *head,
- extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
- void (*func)(struct rcu_head *head)));
- extern void synchronize_kernel(void);
--
-+extern void rcu_barrier(void);
- #endif /* __KERNEL__ */
- #endif /* __LINUX_RCUPDATE_H */
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 0b8c8ca..f8248bc 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_AUDIT) += audit.o
- obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
- obj-$(CONFIG_AUDITFILESYSTEM) += auditfs.o
- obj-$(CONFIG_KPROBES) += kprobes.o
-+obj-$(CONFIG_MARKERS) += marker.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
-diff --git a/kernel/marker.c b/kernel/marker.c
-new file mode 100644
-index 0000000..c4c2cd8
---- /dev/null
-+++ b/kernel/marker.c
-@@ -0,0 +1,851 @@
-+/*
-+ * 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 marker __start___markers[];
-+extern struct marker __stop___markers[];
-+
-+/* Set to 1 to enable marker debug output */
-+const int marker_debug;
-+
-+/*
-+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
-+ * and module markers and the hash table.
-+ */
-+static DEFINE_MUTEX(markers_mutex);
-+
-+/*
-+ * Marker hash table, containing the active markers.
-+ * Protected by module_mutex.
-+ */
-+#define MARKER_HASH_BITS 6
-+#define MARKER_TABLE_SIZE (1 << MARKER_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 marker. It is
-+ * also used to delay the free of multiple probes array until a quiescent state
-+ * is reached.
-+ * marker entries modifications are protected by the markers_mutex.
-+ */
-+struct marker_entry {
-+ struct hlist_node hlist;
-+ char *format;
-+ void (*call)(const struct marker *mdata, /* Probe wrapper */
-+ void *call_private, const char *fmt, ...);
-+ struct marker_probe_closure single;
-+ struct marker_probe_closure *multi;
-+ int refcount; /* Number of times armed. 0 if disarmed. */
-+ struct rcu_head rcu;
-+ void *oldptr;
-+ char rcu_pending:1;
-+ char ptype:1;
-+ char name[0]; /* Contains name'\0'format'\0' */
-+};
-+
-+static struct hlist_head marker_table[MARKER_TABLE_SIZE];
-+
-+/**
-+ * __mark_empty_function - Empty probe callback
-+ * @probe_private: probe private data
-+ * @call_private: call site private data
-+ * @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(void *probe_private, void *call_private,
-+ const char *fmt, va_list *args)
-+{
-+}
-+EXPORT_SYMBOL_GPL(__mark_empty_function);
-+
-+/*
-+ * marker_probe_cb Callback that prepares the variable argument list for probes.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Since we do not use "typical" pointer based RCU in the 1 argument case, we
-+ * need to put a full smp_rmb() in this branch. This is why we do not use
-+ * rcu_dereference() for the pointer read.
-+ */
-+void marker_probe_cb(const struct marker *mdata, void *call_private,
-+ const char *fmt, ...)
-+{
-+ va_list args;
-+ char ptype;
-+
-+ /*
-+ * disabling preemption to make sure the teardown of the callbacks can
-+ * be done correctly when they are in modules and they insure RCU read
-+ * coherency.
-+ */
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ va_start(args, fmt);
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ va_end(args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++) {
-+ va_start(args, fmt);
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ va_end(args);
-+ }
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb);
-+
-+/*
-+ * marker_probe_cb Callback that does not prepare the variable argument list.
-+ * @mdata: pointer of type struct marker
-+ * @call_private: caller site private data
-+ * @fmt: format string
-+ * @...: Variable argument list.
-+ *
-+ * Should be connected to markers "MARK_NOARGS".
-+ */
-+void marker_probe_cb_noarg(const struct marker *mdata,
-+ void *call_private, const char *fmt, ...)
-+{
-+ va_list args; /* not initialized */
-+ char ptype;
-+
-+ preempt_disable();
-+ ptype = ACCESS_ONCE(mdata->ptype);
-+ if (likely(!ptype)) {
-+ marker_probe_func *func;
-+ /* Must read the ptype before ptr. They are not data dependant,
-+ * so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func = ACCESS_ONCE(mdata->single.func);
-+ /* Must read the ptr before private data. They are not data
-+ * dependant, so we put an explicit smp_rmb() here. */
-+ smp_rmb();
-+ func(mdata->single.probe_private, call_private, fmt, &args);
-+ } else {
-+ struct marker_probe_closure *multi;
-+ int i;
-+ /*
-+ * multi points to an array, therefore accessing the array
-+ * depends on reading multi. However, even in this case,
-+ * we must insure that the pointer is read _before_ the array
-+ * data. Same as rcu_dereference, but we need a full smp_rmb()
-+ * in the fast path, so put the explicit barrier here.
-+ */
-+ smp_read_barrier_depends();
-+ multi = ACCESS_ONCE(mdata->multi);
-+ for (i = 0; multi[i].func; i++)
-+ multi[i].func(multi[i].probe_private, call_private, fmt,
-+ &args);
-+ }
-+ preempt_enable();
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);
-+
-+static void free_old_closure(struct rcu_head *head)
-+{
-+ struct marker_entry *entry = container_of(head,
-+ struct marker_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 marker_entry *entry)
-+{
-+ int i;
-+
-+ if (!marker_debug)
-+ return;
-+
-+ if (!entry->ptype) {
-+ printk(KERN_DEBUG "Single probe : %p %p\n",
-+ entry->single.func,
-+ entry->single.probe_private);
-+ } else {
-+ 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 marker_probe_closure *
-+marker_entry_add_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0;
-+ struct marker_probe_closure *old, *new;
-+
-+ WARN_ON(!probe);
-+
-+ debug_print_probes(entry);
-+ old = entry->multi;
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe &&
-+ entry->single.probe_private == probe_private)
-+ return ERR_PTR(-EBUSY);
-+ if (entry->single.func == __mark_empty_function) {
-+ /* 0 -> 1 probes */
-+ entry->single.func = probe;
-+ entry->single.probe_private = probe_private;
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* 1 -> 2 probes */
-+ nr_probes = 1;
-+ old = NULL;
-+ }
-+ } else {
-+ /* (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 marker_probe_closure),
-+ GFP_KERNEL);
-+ if (new == NULL)
-+ return ERR_PTR(-ENOMEM);
-+ if (!old)
-+ new[0] = entry->single;
-+ else
-+ memcpy(new, old,
-+ nr_probes * sizeof(struct marker_probe_closure));
-+ new[nr_probes].func = probe;
-+ new[nr_probes].probe_private = probe_private;
-+ entry->refcount = nr_probes + 1;
-+ entry->multi = new;
-+ entry->ptype = 1;
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+static struct marker_probe_closure *
-+marker_entry_remove_probe(struct marker_entry *entry,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ int nr_probes = 0, nr_del = 0, i;
-+ struct marker_probe_closure *old, *new;
-+
-+ old = entry->multi;
-+
-+ debug_print_probes(entry);
-+ if (!entry->ptype) {
-+ /* 0 -> N is an error */
-+ WARN_ON(entry->single.func == __mark_empty_function);
-+ /* 1 -> 0 probes */
-+ WARN_ON(probe && entry->single.func != probe);
-+ WARN_ON(entry->single.probe_private != probe_private);
-+ entry->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ debug_print_probes(entry);
-+ return NULL;
-+ } else {
-+ /* (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->single.func = __mark_empty_function;
-+ entry->refcount = 0;
-+ entry->ptype = 0;
-+ } else if (nr_probes - nr_del == 1) {
-+ /* N -> 1, (N > 1) */
-+ for (i = 0; old[i].func; i++)
-+ if ((probe && old[i].func != probe) ||
-+ old[i].probe_private != probe_private)
-+ entry->single = old[i];
-+ entry->refcount = 1;
-+ entry->ptype = 0;
-+ } else {
-+ int j = 0;
-+ /* N -> M, (N > 1, M > 1) */
-+ /* + 1 for NULL */
-+ new = kzalloc((nr_probes - nr_del + 1)
-+ * sizeof(struct marker_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->ptype = 1;
-+ entry->multi = new;
-+ }
-+ debug_print_probes(entry);
-+ return old;
-+}
-+
-+/*
-+ * 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 struct marker_entry *add_marker(const char *name, const char *format)
-+{
-+ 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\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 marker_entry) + name_len + format_len,
-+ GFP_KERNEL);
-+ if (!e)
-+ return ERR_PTR(-ENOMEM);
-+ memcpy(&e->name[0], name, name_len);
-+ if (format) {
-+ e->format = &e->name[name_len];
-+ memcpy(e->format, format, format_len);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ trace_mark(core_marker_format, "name %s format %s",
-+ e->name, e->format);
-+ } else {
-+ e->format = NULL;
-+ e->call = marker_probe_cb;
-+ }
-+ e->single.func = __mark_empty_function;
-+ e->single.probe_private = NULL;
-+ e->multi = NULL;
-+ e->ptype = 0;
-+ e->refcount = 0;
-+ e->rcu_pending = 0;
-+ hlist_add_head(&e->hlist, head);
-+ return e;
-+}
-+
-+/*
-+ * Remove the marker from the marker hash table. Must be called with mutex_lock
-+ * held.
-+ */
-+static int 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;
-+ 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)
-+ return -ENOENT;
-+ if (e->single.func != __mark_empty_function)
-+ return -EBUSY;
-+ hlist_del(&e->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if (e->rcu_pending)
-+ rcu_barrier();
-+ kfree(e);
-+ return 0;
-+}
-+
-+/*
-+ * 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);
-+ if (strcmp(e->format, MARK_NOARGS) == 0)
-+ e->call = marker_probe_cb_noarg;
-+ else
-+ e->call = marker_probe_cb;
-+ e->single = (*entry)->single;
-+ e->multi = (*entry)->multi;
-+ e->ptype = (*entry)->ptype;
-+ e->refcount = (*entry)->refcount;
-+ e->rcu_pending = 0;
-+ hlist_add_before(&e->hlist, &(*entry)->hlist);
-+ hlist_del(&(*entry)->hlist);
-+ /* Make sure the call_rcu has been executed */
-+ if ((*entry)->rcu_pending)
-+ rcu_barrier();
-+ 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 marker *elem,
-+ int active)
-+{
-+ 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;
-+ }
-+
-+ /*
-+ * probe_cb setup (statically known) is done here. It is
-+ * asynchronous with the rest of execution, therefore we only
-+ * pass from a "safe" callback (with argument) to an "unsafe"
-+ * callback (does not set arguments).
-+ */
-+ elem->call = (*entry)->call;
-+ /*
-+ * Sanity check :
-+ * We only update the single probe private data when the ptr is
-+ * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
-+ */
-+ WARN_ON(elem->single.func != __mark_empty_function
-+ && elem->single.probe_private
-+ != (*entry)->single.probe_private &&
-+ !elem->ptype);
-+ elem->single.probe_private = (*entry)->single.probe_private;
-+ /*
-+ * Make sure the private data is valid when we update the
-+ * single probe ptr.
-+ */
-+ smp_wmb();
-+ elem->single.func = (*entry)->single.func;
-+ /*
-+ * 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);
-+ /*
-+ * Update the function or multi probe array pointer before setting the
-+ * ptype.
-+ */
-+ smp_wmb();
-+ elem->ptype = (*entry)->ptype;
-+ elem->state = active;
-+
-+ 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 marker *elem)
-+{
-+ /* leave "call" as is. It is known statically. */
-+ elem->state = 0;
-+ elem->single.func = __mark_empty_function;
-+ /* Update the function before setting the ptype */
-+ smp_wmb();
-+ elem->ptype = 0; /* single probe */
-+ /*
-+ * 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
-+ *
-+ * Updates the probe callback corresponding to a range of markers.
-+ */
-+void marker_update_probe_range(struct marker *begin,
-+ struct marker *end)
-+{
-+ struct marker *iter;
-+ struct marker_entry *mark_entry;
-+
-+ mutex_lock(&markers_mutex);
-+ for (iter = begin; iter < end; iter++) {
-+ mark_entry = get_marker(iter->name);
-+ if (mark_entry) {
-+ set_marker(&mark_entry, iter,
-+ !!mark_entry->refcount);
-+ /*
-+ * ignore error, continue
-+ */
-+ } else {
-+ disable_marker(iter);
-+ }
-+ }
-+ mutex_unlock(&markers_mutex);
-+}
-+
-+/*
-+ * 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.
-+ *
-+ * Internal callback only changed before the first probe is connected to it.
-+ * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
-+ * transitions. All other transitions will leave the old private data valid.
-+ * This makes the non-atomicity of the callback/private data updates valid.
-+ *
-+ * "special case" updates :
-+ * 0 -> 1 callback
-+ * 1 -> 0 callback
-+ * 1 -> 2 callbacks
-+ * 2 -> 1 callbacks
-+ * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
-+ * Site effect : marker_set_format may delete the marker entry (creating a
-+ * replacement).
-+ */
-+static void marker_update_probes(void)
-+{
-+ /* Core kernel markers */
-+ marker_update_probe_range(__start___markers, __stop___markers);
-+ /* Markers in modules. */
-+ module_update_markers();
-+}
-+
-+/**
-+ * marker_probe_register - Connect a probe to a marker
-+ * @name: marker name
-+ * @format: format string
-+ * @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 marker_probe_register(const char *name, const char *format,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ entry = add_marker(name, format);
-+ if (IS_ERR(entry)) {
-+ ret = PTR_ERR(entry);
-+ goto end;
-+ }
-+ }
-+ /*
-+ * If we detect that a call_rcu is pending for this marker,
-+ * make sure it's executed now.
-+ */
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_add_probe(entry, probe, probe_private);
-+ if (IS_ERR(old)) {
-+ ret = PTR_ERR(old);
-+ goto end;
-+ }
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_register);
-+
-+/**
-+ * marker_probe_unregister - Disconnect a probe from a marker
-+ * @name: marker name
-+ * @probe: probe function pointer
-+ * @probe_private: probe private data
-+ *
-+ * Returns the private data given to marker_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 marker_probe_unregister(const char *name,
-+ marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ struct marker_probe_closure *old;
-+ int ret = 0;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, probe, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker(name);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister);
-+
-+static struct marker_entry *
-+get_marker_from_private_data(marker_probe_func *probe, void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ unsigned int i;
-+ struct hlist_head *head;
-+ struct hlist_node *node;
-+
-+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
-+ head = &marker_table[i];
-+ hlist_for_each_entry(entry, node, head, hlist) {
-+ if (!entry->ptype) {
-+ if (entry->single.func == probe
-+ && entry->single.probe_private
-+ == probe_private)
-+ return entry;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ closure = entry->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func == probe &&
-+ closure[i].probe_private
-+ == probe_private)
-+ return entry;
-+ }
-+ }
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * marker_probe_unregister_private_data - Disconnect a probe from a marker
-+ * @probe: probe function
-+ * @probe_private: probe private data
-+ *
-+ * Unregister a probe by providing the registered private data.
-+ * Only removes the first marker found in hash table.
-+ * Return 0 on success or error value.
-+ * 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 marker_probe_unregister_private_data(marker_probe_func *probe,
-+ void *probe_private)
-+{
-+ struct marker_entry *entry;
-+ int ret = 0;
-+ struct marker_probe_closure *old;
-+
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ if (!entry) {
-+ ret = -ENOENT;
-+ goto end;
-+ }
-+ if (entry->rcu_pending)
-+ rcu_barrier();
-+ old = marker_entry_remove_probe(entry, NULL, probe_private);
-+ mutex_unlock(&markers_mutex);
-+ marker_update_probes(); /* may update entry */
-+ mutex_lock(&markers_mutex);
-+ entry = get_marker_from_private_data(probe, probe_private);
-+ WARN_ON(!entry);
-+ entry->oldptr = old;
-+ entry->rcu_pending = 1;
-+ /* write rcu_pending before calling the RCU callback */
-+ smp_wmb();
-+ call_rcu(&entry->rcu, free_old_closure);
-+ remove_marker(entry->name); /* Ignore busy error message */
-+end:
-+ mutex_unlock(&markers_mutex);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
-+
-+/**
-+ * marker_get_private_data - Get a marker's probe private data
-+ * @name: marker name
-+ * @probe: probe to match
-+ * @num: get the nth matching probe's private data
-+ *
-+ * Returns the nth private data pointer (starting from 0) matching, or an
-+ * ERR_PTR.
-+ * 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, marker_probe_func *probe,
-+ int num)
-+{
-+ 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 i;
-+
-+ head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
-+ hlist_for_each_entry(e, node, head, hlist) {
-+ if (!strcmp(name, e->name)) {
-+ if (!e->ptype) {
-+ if (num == 0 && e->single.func == probe)
-+ return e->single.probe_private;
-+ else
-+ break;
-+ } else {
-+ struct marker_probe_closure *closure;
-+ int match = 0;
-+ closure = e->multi;
-+ for (i = 0; closure[i].func; i++) {
-+ if (closure[i].func != probe)
-+ continue;
-+ if (match++ == num)
-+ return closure[i].probe_private;
-+ }
-+ }
-+ }
-+ }
-+ return ERR_PTR(-ENOENT);
-+}
-+EXPORT_SYMBOL_GPL(marker_get_private_data);
-diff --git a/kernel/module.c b/kernel/module.c
-index 624e7ee..ae16b04 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1507,6 +1507,8 @@ static struct module *load_module(void __user *umod,
- struct exception_table_entry *extable;
- mm_segment_t old_fs;
- int gpgsig_ok;
-+ unsigned int markersindex;
-+ unsigned int markersstringsindex;
-
- DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
- umod, len, uargs);
-@@ -1739,6 +1741,9 @@ static struct module *load_module(void __user *umod,
- tainted |= 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++) {
-@@ -1762,6 +1767,12 @@ static struct module *load_module(void __user *umod,
- goto cleanup;
- }
-
-+#ifdef CONFIG_MARKERS
-+ mod->markers = (void *)sechdrs[markersindex].sh_addr;
-+ mod->num_markers =
-+ sechdrs[markersindex].sh_size / sizeof(*mod->markers);
-+#endif
-+
- /* Set up and sort exception table */
- mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
- mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
-@@ -1773,6 +1784,12 @@ static struct module *load_module(void __user *umod,
-
- add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-
-+#ifdef CONFIG_MARKERS
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+#endif
-+
- err = module_finalize(hdr, sechdrs, mod);
- if (err < 0)
- goto cleanup;
-@@ -2190,6 +2207,20 @@ void struct_module(struct module *mod) { return; }
- EXPORT_SYMBOL(struct_module);
- #endif
-
-+#ifdef CONFIG_MARKERS
-+void module_update_markers(void)
-+{
-+ struct module *mod;
-+
-+ down(&module_mutex);
-+ list_for_each_entry(mod, &modules, list)
-+ if (!tainted)
-+ marker_update_probe_range(mod->markers,
-+ mod->markers + mod->num_markers);
-+ up(&module_mutex);
-+}
-+#endif
-+
- static int __init modules_init(void)
- {
- return subsystem_register(&module_subsys);
-diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
-index 1b16bfc..20ade31 100644
---- a/kernel/rcupdate.c
-+++ b/kernel/rcupdate.c
-@@ -46,6 +46,7 @@
- #include <linux/notifier.h>
- #include <linux/rcupdate.h>
- #include <linux/cpu.h>
-+#include <linux/mutex.h>
-
- /* Definition for rcupdate control block. */
- struct rcu_ctrlblk rcu_ctrlblk =
-@@ -98,6 +99,10 @@ void fastcall call_rcu(struct rcu_head *head,
- local_irq_restore(flags);
- }
-
-+static atomic_t rcu_barrier_cpu_count;
-+static DEFINE_MUTEX(rcu_barrier_mutex);
-+static struct completion rcu_barrier_completion;
-+
- /**
- * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
- * @head: structure to be used for queueing the RCU updates.
-@@ -410,6 +415,44 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
- return NOTIFY_OK;
- }
-
-+static void rcu_barrier_callback(struct rcu_head *notused)
-+{
-+ if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-+ complete(&rcu_barrier_completion);
-+}
-+
-+/*
-+ * Called with preemption disabled, and from cross-cpu IRQ context.
-+ */
-+static void rcu_barrier_func(void *notused)
-+{
-+ int cpu = smp_processor_id();
-+ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
-+ struct rcu_head *head;
-+
-+ head = &rdp->barrier;
-+ atomic_inc(&rcu_barrier_cpu_count);
-+ call_rcu(head, rcu_barrier_callback);
-+}
-+
-+/**
-+ * rcu_barrier - Wait until all the in-flight RCUs are complete.
-+ */
-+void rcu_barrier(void)
-+{
-+ BUG_ON(in_interrupt());
-+ /* Take cpucontrol mutex to protect against CPU hotplug */
-+ mutex_lock(&rcu_barrier_mutex);
-+ init_completion(&rcu_barrier_completion);
-+ atomic_set(&rcu_barrier_cpu_count, 0);
-+ on_each_cpu(rcu_barrier_func, NULL, 0, 1);
-+ wait_for_completion(&rcu_barrier_completion);
-+ mutex_unlock(&rcu_barrier_mutex);
-+}
-+EXPORT_SYMBOL_GPL(rcu_barrier);
-+
-+
-+
- static struct notifier_block __devinitdata rcu_nb = {
- .notifier_call = rcu_cpu_notify,
- };
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index b3d31b5..b100a32 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -13,6 +13,7 @@
- # 2) modpost is then used to
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
-+# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
- # 5) compile all <module>.mod.c files
- # 6) final link of the module to a <module.ko> file
-
-@@ -40,6 +41,11 @@ include scripts/Makefile.lib
-
- symverfile := $(objtree)/Module.symvers
-
-+kernelmarkersfile := $(objtree)/Module.markers
-+modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
-+
-+markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
-+
- # Step 1), find all modules listed in $(MODVERDIR)/
- __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
- modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
-@@ -53,16 +59,27 @@ quiet_cmd_modpost = MODPOST
- cmd_modpost = scripts/mod/modpost \
- $(if $(CONFIG_MODVERSIONS),-m) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
-+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
-+ $(if $(CONFIG_MARKERS),-M $(markersfile)) \
- $(filter-out FORCE,$^)
-
- .PHONY: __modpost
- __modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
- $(call cmd,modpost)
-
-+quiet_cmd_kernel-mod = MODPOST $@
-+ cmd_kernel-mod = $(cmd_modpost) $@
-+
-+vmlinux.o: FORCE
-+ $(call cmd,kernel-mod)
-+
- # Declare generated files as targets for modpost
- $(symverfile): __modpost ;
- $(modules:.ko=.mod.c): __modpost ;
-
-+ifdef CONFIG_MARKERS
-+$(markersfile): __modpost ;
-+endif
-
- # Step 5), compile all *.mod.c files
-
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 2a174e5..c25948c 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -10,7 +10,8 @@
- *
- * Usage: modpost vmlinux module1.o module2.o ...
- */
--
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <ctype.h>
- #include "modpost.h"
-
-@@ -289,7 +290,9 @@ parse_elf(struct elf_info *info, const char *filename)
- if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
- info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
- info->modinfo_len = sechdrs[i].sh_size;
-- }
-+ } else if (strcmp(secstrings+sechdrs[i].sh_name, "__markers_strings") == 0)
-+ info->markers_strings_sec = i;
-+
- if (sechdrs[i].sh_type != SHT_SYMTAB)
- continue;
-
-@@ -397,6 +400,63 @@ is_vmlinux(const char *modname)
- return strcmp(myname, "vmlinux") == 0;
- }
-
-+static void get_markers(struct elf_info *info, struct module *mod)
-+{
-+ const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-+ const char *strings = (const char *) info->hdr + sh->sh_offset;
-+ const Elf_Sym *sym, *first_sym, *last_sym;
-+ size_t n;
-+
-+
-+ if (!info->markers_strings_sec)
-+ return;
-+
-+ /*
-+ * First count the strings. We look for all the symbols defined
-+ * in the __markers_strings section named __mstrtab_*. For
-+ * these local names, the compiler puts a random .NNN suffix on,
-+ * so the names don't correspond exactly.
-+ */
-+ first_sym = last_sym = NULL;
-+ n = 0;
-+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ if (first_sym == NULL)
-+ first_sym = sym;
-+ last_sym = sym;
-+ ++n;
-+ }
-+
-+ if (n == 0)
-+ return;
-+ /*
-+ * Now collect each name and format into a line for the output.
-+ * Lines look like:
-+ * marker_name vmlinux marker %s format %d
-+ * The format string after the second \t can use whitespace.
-+ */
-+ mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-+ mod->nmarkers = n;
-+
-+ n = 0;
-+ for (sym = first_sym; sym <= last_sym; sym++)
-+ if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-+ sym->st_shndx == info->markers_strings_sec &&
-+ !strncmp(info->strtab + sym->st_name,
-+ "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-+ const char *name = strings + sym->st_value;
-+ const char *fmt = strchr(name, '\0') + 1;
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+ mod->markers[n++] = line;
-+ }
-+}
-+
-+
- void
- read_symbols(char *modname)
- {
-@@ -426,6 +486,7 @@ read_symbols(char *modname)
- }
- maybe_frob_version(modname, info.modinfo, info.modinfo_len,
- (void *)info.modinfo - (void *)info.hdr);
-+ get_markers(&info, mod);
- parse_elf_finish(&info);
-
- /* Our trick to get versioning for struct_module - it's
-@@ -682,6 +743,92 @@ write_dump(const char *fname)
- write_if_changed(&buf, fname);
- }
-
-+static void add_marker(struct module *mod, const char *name, const char *fmt)
-+{
-+ char *line = NULL;
-+ asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-+ NOFAIL(line);
-+
-+ mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-+ sizeof mod->markers[0])));
-+ mod->markers[mod->nmarkers++] = line;
-+}
-+
-+static void read_markers(const char *fname)
-+{
-+ unsigned long size, pos = 0;
-+ void *file = grab_file(fname, &size);
-+ char *line;
-+
-+ if (!file) /* No old markers, silently ignore */
-+ return;
-+
-+ while ((line = get_next_line(&pos, file, size))) {
-+ char *marker, *modname, *fmt;
-+ struct module *mod;
-+
-+ marker = line;
-+ modname = strchr(marker, '\t');
-+ if (!modname)
-+ goto fail;
-+ *modname++ = '\0';
-+ fmt = strchr(modname, '\t');
-+ if (!fmt)
-+ goto fail;
-+ *fmt++ = '\0';
-+ if (*marker == '\0' || *modname == '\0')
-+ goto fail;
-+
-+ mod = find_module(modname);
-+ if (!mod) {
-+ if (is_vmlinux(modname))
-+ have_vmlinux = 1;
-+ mod = new_module(NOFAIL(strdup(modname)));
-+ mod->skip = 1;
-+ }
-+
-+ add_marker(mod, marker, fmt);
-+ }
-+ return;
-+fail:
-+ fatal("parse error in markers list file\n");
-+}
-+
-+static int compare_strings(const void *a, const void *b)
-+{
-+ return strcmp(*(const char **) a, *(const char **) b);
-+}
-+
-+static void write_markers(const char *fname)
-+{
-+ struct buffer buf = { };
-+ struct module *mod;
-+ size_t i;
-+
-+ for (mod = modules; mod; mod = mod->next)
-+ if (mod->markers != NULL) {
-+ /*
-+ * Sort the strings so we can skip duplicates when
-+ * we write them out.
-+ */
-+ qsort(mod->markers, mod->nmarkers,
-+ sizeof mod->markers[0], &compare_strings);
-+ for (i = 0; i < mod->nmarkers; ++i) {
-+ char *line = mod->markers[i];
-+ buf_write(&buf, line, strlen(line));
-+ while (i + 1 < mod->nmarkers &&
-+ !strcmp(mod->markers[i],
-+ mod->markers[i + 1]))
-+ free(mod->markers[i++]);
-+ free(mod->markers[i]);
-+ }
-+ free(mod->markers);
-+ mod->markers = NULL;
-+ }
-+
-+ write_if_changed(&buf, fname);
-+}
-+
- int
- main(int argc, char **argv)
- {
-@@ -690,8 +837,10 @@ main(int argc, char **argv)
- char fname[SZ];
- char *dump_read = NULL, *dump_write = NULL;
- int opt;
-+ char *markers_read = NULL;
-+ char *markers_write = NULL;
-
-- while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
-+ while ((opt = getopt(argc, argv, "i:mo:M:K:")) != -1) {
- switch(opt) {
- case 'i':
- dump_read = optarg;
-@@ -702,6 +851,12 @@ main(int argc, char **argv)
- case 'o':
- dump_write = optarg;
- break;
-+ case 'M':
-+ markers_write = optarg;
-+ break;
-+ case 'K':
-+ markers_read = optarg;
-+ break;
- default:
- exit(1);
- }
-@@ -732,6 +887,12 @@ main(int argc, char **argv)
- if (dump_write)
- write_dump(dump_write);
-
-+ if (markers_read)
-+ read_markers(markers_read);
-+
-+ if (markers_write)
-+ write_markers(markers_write);
-+
- return 0;
- }
-
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index 4871343..d79d7ea 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -18,6 +18,7 @@
- #define Elf_Sym Elf32_Sym
- #define ELF_ST_BIND ELF32_ST_BIND
- #define ELF_ST_TYPE ELF32_ST_TYPE
-+#define Elf_Section Elf32_Half
-
- #else
-
-@@ -26,7 +27,7 @@
- #define Elf_Sym Elf64_Sym
- #define ELF_ST_BIND ELF64_ST_BIND
- #define ELF_ST_TYPE ELF64_ST_TYPE
--
-+#define Elf_Section Elf64_Half
- #endif
-
- #if KERNEL_ELFDATA != HOST_ELFDATA
-@@ -77,6 +78,8 @@ struct module {
- int has_init;
- int has_cleanup;
- struct buffer dev_table_buf;
-+ char **markers;
-+ size_t nmarkers;
- };
-
- struct elf_info {
-@@ -85,6 +88,7 @@ struct elf_info {
- Elf_Shdr *sechdrs;
- Elf_Sym *symtab_start;
- Elf_Sym *symtab_stop;
-+ Elf_Section markers_strings_sec;
- const char *strtab;
- char *modinfo;
- unsigned int modinfo_len;
More information about the Kernelpatches-commits
mailing list