Linux Kernel Markers
Subsystems (20)
cover Linux Kernel Markers
Hi,
This is the latest release of the Linux Kernel Markers, adapted to use the new "immediate values" infrastructure to provide low impact when compiled-in but disabled.
It applies at the end of the 2.6.22-rc4-mm2 series, after the "immediate values" patches, in this order:
use-extra_rwdata-in-architectures.patch
# linux-kernel-markers-architecture-independent-code.patch linux-kernel-markers-kconfig-menus.patch linux-kernel-markers-documentation.patch linux-kernel-markers-port-blktrace-to-markers.patch
Regards,
Mathieu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 1/5 Use EXTRARW_DATA in architectures
EXTRARW_DATA adds a place to declare rw data that will not be mixed with the .data content; therefore limiting data cache pollution when data is put in the EXTRARW_DATA sections.
---
arch/alpha/kernel/vmlinux.lds.S | 1 + arch/arm/kernel/vmlinux.lds.S | 1 + arch/arm26/kernel/vmlinux-arm26-xip.lds.in | 1 + arch/arm26/kernel/vmlinux-arm26.lds.in | 1 + arch/avr32/kernel/vmlinux.lds.c | 1 + arch/cris/arch-v10/vmlinux.lds.S | 1 + arch/cris/arch-v32/vmlinux.lds.S | 1 + arch/frv/kernel/vmlinux.lds.S | 1 + arch/h8300/kernel/vmlinux.lds.S | 3 ++- arch/i386/kernel/vmlinux.lds.S | 1 + arch/ia64/kernel/vmlinux.lds.S | 1 + arch/m32r/kernel/vmlinux.lds.S | 1 + arch/m68k/kernel/vmlinux-std.lds | 1 + arch/m68k/kernel/vmlinux-sun3.lds | 1 + arch/m68knommu/kernel/vmlinux.lds.S | 1 + arch/mips/kernel/vmlinux.lds.S | 3 +-- arch/parisc/kernel/vmlinux.lds.S | 1 + arch/powerpc/kernel/vmlinux.lds.S | 2 ++ arch/ppc/kernel/vmlinux.lds.S | 1 + arch/s390/kernel/vmlinux.lds.S | 1 + arch/sh/kernel/vmlinux.lds.S | 2 +- arch/sh64/kernel/vmlinux.lds.S | 1 + arch/sparc/kernel/vmlinux.lds.S | 1 + arch/sparc64/kernel/vmlinux.lds.S | 1 + arch/um/kernel/dyn.lds.S | 1 + arch/um/kernel/uml.lds.S | 1 + arch/v850/kernel/vmlinux.lds.S | 1 + arch/x86_64/kernel/vmlinux.lds.S | 1 + arch/xtensa/kernel/vmlinux.lds.S | 4 +++- include/asm-generic/vmlinux.lds.h | 5 +++++ 30 files changed, 38 insertions(+), 5 deletions(-)
arch/alpha/kernel/vmlinux.lds.S +1 -0
@@ -90,6 +90,7 @@ _data = .; .data : { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/arm/kernel/vmlinux.lds.S +1 -0
@@ -159,6 +159,7 @@ * and the usual data section */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS _edata = .;
arch/arm26/kernel/vmlinux-arm26-xip.lds.in +1 -0
@@ -112,6 +112,7 @@ * and the usual data section */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS *(.init.data)
arch/arm26/kernel/vmlinux-arm26.lds.in +1 -0
@@ -107,6 +107,7 @@ * and the usual data section */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS _edata = .;
arch/avr32/kernel/vmlinux.lds.c +1 -0
@@ -113,6 +113,7 @@/* And the rest... */ *(.data.rel*) DATA_DATA + EXTRARW_DATA CONSTRUCTORS _edata = .;
arch/cris/arch-v10/vmlinux.lds.S +1 -0
@@ -45,6 +45,7 @@ __Sdata = . ; .data : { /* Data */ *(.data) + EXTRARW_DATA } __edata = . ; /* End of data section */ _edata = . ;
arch/cris/arch-v32/vmlinux.lds.S +1 -0
@@ -50,6 +50,7 @@ __Sdata = . ; .data : { /* Data */ *(.data) + EXTRARW_DATA } __edata = . ; /* End of data section. */ _edata = . ;
arch/frv/kernel/vmlinux.lds.S +1 -0
@@ -139,6 +139,7 @@ DATA_DATA *(.data.*) *(.exit.data) + EXTRARW_DATA CONSTRUCTORS }
arch/h8300/kernel/vmlinux.lds.S +2 -1
@@ -105,7 +105,8 @@ . = ALIGN(0x4) ; DATA_DATA . = ALIGN(0x4) ; - *(.data.*) + *(.data.*) + EXTRARW_DATA . = ALIGN(0x4) ; ___init_begin = .;
arch/i386/kernel/vmlinux.lds.S +1 -0
@@ -77,6 +77,7 @@ . = ALIGN(4096); .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS } :data
arch/ia64/kernel/vmlinux.lds.S +1 -0
@@ -216,6 +216,7 @@ .data : AT(ADDR(.data) - LOAD_OFFSET) { DATA_DATA + EXTRARW_DATA *(.data1) *(.gnu.linkonce.d*) CONSTRUCTORS
arch/m32r/kernel/vmlinux.lds.S +1 -0
@@ -51,6 +51,7 @@ *(.spu) *(.spi) DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/m68k/kernel/vmlinux-std.lds +1 -0
@@ -29,6 +29,7 @@ .data : { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/m68k/kernel/vmlinux-sun3.lds +1 -0
@@ -24,6 +24,7 @@ .data : { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS . = ALIGN(16); /* Exception table */ __start___ex_table = .;
arch/m68knommu/kernel/vmlinux.lds.S +1 -0
@@ -134,6 +134,7 @@ . = ALIGN(4); _sdata = . ; DATA_DATA + EXTRARW_DATA . = ALIGN(8192) ; *(.data.init_task) _edata = . ;
arch/mips/kernel/vmlinux.lds.S +1 -2
@@ -61,9 +61,8 @@ */ . = ALIGN(_PAGE_SIZE); *(.data.init_task) - DATA_DATA - + EXTRARW_DATA CONSTRUCTORS } _gp = . + 0x8000;
arch/parisc/kernel/vmlinux.lds.S +1 -0
@@ -92,6 +92,7 @@ . = ALIGN(L1_CACHE_BYTES); .data : { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/powerpc/kernel/vmlinux.lds.S +2 -0
@@ -170,11 +170,13 @@ DATA_DATA *(.sdata) *(.got.plt) *(.got) + EXTRARW_DATA } #else .data : { *(.data .data.rel* .toc1) *(.branch_lt) + EXTRARW_DATA } .opd : {
arch/ppc/kernel/vmlinux.lds.S +1 -0
@@ -73,6 +73,7 @@ *(.sdata2) *(.got.plt) *(.got) *(.dynamic) + EXTRARW_DATA CONSTRUCTORS }
arch/s390/kernel/vmlinux.lds.S +1 -0
@@ -49,6 +49,7 @@ .data : { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/sh/kernel/vmlinux.lds.S +1 -1
@@ -49,7 +49,7 @@ *(.initrd) . = ALIGN(PAGE_SIZE); __rd_end = .; - + EXTRARW_DATA CONSTRUCTORS }
arch/sh64/kernel/vmlinux.lds.S +1 -0
@@ -79,6 +79,7 @@ .data : C_PHYS(.data) { /* Data */ DATA_DATA + EXTRARW_DATA CONSTRUCTORS }
arch/sparc/kernel/vmlinux.lds.S +1 -0
@@ -23,6 +23,7 @@ .data : { DATA_DATA + EXTRARW_DATA CONSTRUCTORS } .data1 : { *(.data1) }
arch/sparc64/kernel/vmlinux.lds.S +1 -0
@@ -29,6 +29,7 @@ .data : { DATA_DATA + EXTRARW_DATA CONSTRUCTORS } .data1 : { *(.data1) }
arch/um/kernel/dyn.lds.S +1 -0
@@ -101,6 +101,7 @@ *(.data.init_irqstack) DATA_DATA *(.data.* .gnu.linkonce.d.*) + EXTRARW_DATA SORT(CONSTRUCTORS) } .data1 : { *(.data1) }
arch/um/kernel/uml.lds.S +1 -0
@@ -63,6 +63,7 @@ *(.data.init_irqstack) DATA_DATA *(.gnu.linkonce.d*) + EXTRARW_DATA CONSTRUCTORS } .data1 : { *(.data1) }
arch/v850/kernel/vmlinux.lds.S +1 -0
@@ -116,6 +116,7 @@ DATA_DATA \ *(.exit.data) /* 2.5 convention */ \ *(.data.exit) /* 2.4 convention */ \ + EXTRARW_DATA \ . = ALIGN (16) ; \ *(.data.cacheline_aligned) \ . = ALIGN (0x2000) ; \
arch/x86_64/kernel/vmlinux.lds.S +1 -0
@@ -63,6 +63,7 @@ /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { DATA_DATA + EXTRARW_DATA CONSTRUCTORS } :data
arch/xtensa/kernel/vmlinux.lds.S +3 -1
@@ -118,7 +118,9 @@ _fdata = .; .data : { - *(.data) CONSTRUCTORS + *(.data) + EXTRARW_DATA + CONSTRUCTORS . = ALIGN(XCHAL_ICACHE_LINESIZE); *(.data.cacheline_aligned) }
include/asm-generic/vmlinux.lds.h +5 -0
@@ -150,6 +150,11 @@* All archs are supposed to use RO_DATA() */ #define RODATA RO_DATA(4096) +/* EXTRARW_DATA adds a place to declare rw data that will not be mixed with the +* .data content; therefore limiting data cache pollution when data is put in +* the EXTRARW_DATA sections. */ +#define EXTRARW_DATA +#define SECURITY_INIT \ .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__security_initcall_start) = .; \
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [patch 1/5] Use EXTRARW_DATA in architectures
Hi Mathieu.
Quoted 3 lines · Mathieu Desnoyers
EXTRARW_DATAadds a place to declare rw data that will not be mixed with the .data content; therefore limiting data cache pollution when data is put in theEXTRARW_DATAsections.
I would suggest to embed this inside DATA_DATA in vmlinux.lds.h That seems reasonsable to do instead of adding it right after DATA_DATA for all archs.
From your patch it looks like I originally missed out powerpc + xtensa when introducing DATA_DATA - would be nice if you could fix that.
Sam
PATCH 1/1 Use DATA_DATA in cris
Quoted 4 lines · * Sam Ravnborg ([email protected]) wrote:
From your patch it looks like I originally missed out powerpc + xtensa when introducing
DATA_DATA- would be nice if you could fix that.
Use DATA_DATA in CRIS
--- arch/cris/arch-v10/vmlinux.lds.S | 2 +- arch/cris/arch-v32/vmlinux.lds.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/cris/arch-v10/vmlinux.lds.S +1 -1
@@ -44,7 +44,7 @@ ___data_start = . ; __Sdata = . ; .data : { /* Data */ - *(.data) + DATA_DATA } __edata = . ; /* End of data section */ _edata = . ;
arch/cris/arch-v32/vmlinux.lds.S +1 -1
@@ -49,7 +49,7 @@ ___data_start = . ; __Sdata = . ; .data : { /* Data */ - *(.data) + DATA_DATA } __edata = . ; /* End of data section. */ _edata = . ;
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 1/1 Add missing DATA_DATA to powerpc
In reply to Sam RavnborgQuoted 5 lines · * Sam Ravnborg ([email protected]) wrote:
From your patch it looks like I originally missed out powerpc + xtensa when introducing
DATA_DATA- would be nice if you could fix that.Sam
Add missing DATA_DATA in powerpc
--
arch/powerpc/kernel/vmlinux.lds.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/kernel/vmlinux.lds.S +3 -1
@@ -173,7 +173,9 @@ } #else .data : { - *(.data .data.rel* .toc1) + DATA_DATA + *(.data.rel*) + *(.toc1) *(.branch_lt) }
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 1/1 Use DATA_DATA in xtensa
In reply to Sam RavnborgQuoted 5 lines · * Sam Ravnborg ([email protected]) wrote:
From your patch it looks like I originally missed out powerpc + xtensa when introducing
DATA_DATA- would be nice if you could fix that.Sam
Use DATA_DATA in xtensa
--- arch/xtensa/kernel/vmlinux.lds.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/xtensa/kernel/vmlinux.lds.S +2 -1
@@ -118,7 +118,8 @@ _fdata = .; .data : { - *(.data) CONSTRUCTORS + DATA_DATA + CONSTRUCTORS . = ALIGN(XCHAL_ICACHE_LINESIZE); *(.data.cacheline_aligned) }
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [patch 1/5] Use EXTRARW_DATA in architectures
In reply to Sam RavnborgQuoted 11 lines · * Sam Ravnborg ([email protected]) wrote:
Hi Mathieu.
Quoted 3 lines · Mathieu Desnoyers
EXTRARW_DATAadds a place to declare rw data that will not be mixed with the .data content; therefore limiting data cache pollution when data is put in theEXTRARW_DATAsections.I would suggest to embed this inside
DATA_DATAinvmlinux.lds.hThat seems reasonsable to do instead of adding it right afterDATA_DATAfor all archs.
Yes, it will be in my next release,
Quoted 5 lines
From your patch it looks like I originally missed out powerpc + xtensa when introducing
DATA_DATA- would be nice if you could fix that.Sam
Done.
Thanks,
Mathieu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 2/5 Linux Kernel Markers, architecture independent code.
In reply to Mathieu DesnoyersThe marker activation functions sits in kernel/marker.c. A linked list is used to keep track of the armed/disarmed markers, so they can be activated at module load time.
---
include/asm-generic/vmlinux.lds.h | 11 include/linux/marker.h | 108 ++++++++ include/linux/module.h | 5 kernel/Makefile | 1 kernel/marker.c | 491 ++++++++++++++++++++++++++++++++++++++ kernel/module.c | 19 + 6 files changed, 634 insertions(+), 1 deletion(-)
include/asm-generic/vmlinux.lds.h +10 -1
@@ -129,6 +129,11 @@ VMLINUX_SYMBOL(__stop___immediate) = .; \ } \ \ +/* Markers: strings */ \ + __markers_strings : AT(ADDR(__markers_strings) - LOAD_OFFSET) { \ + *(__markers_strings) \ + } \ + \/* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \
@@ -153,7 +158,11 @@/* EXTRARW_DATA adds a place to declare rw data that will not be mixed with the * .data content; therefore limiting data cache pollution when data is put in * the EXTRARW_DATA sections. */ -#define EXTRARW_DATA +#define EXTRARW_DATA \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__start___markers) = .; \ + *(__markers) \ + VMLINUX_SYMBOL(__stop___markers) = .;#define SECURITY_INIT \ .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
include/linux/marker.h new file +108 -0
108 lines not on this page · raw message
include/linux/module.h +5 -0
@@ -16,6 +16,7 @@#include <linux/kobject.h> #include <linux/moduleparam.h> #include <linux/immediate.h> +#include <linux/marker.h> #include <asm/local.h> #include <asm/module.h>
@@ -364,6 +365,10 @@const struct __immediate *immediates;unsigned int num_immediates;#endif +#ifdef CONFIG_MARKERS +struct __mark_marker *markers; +unsigned int num_markers; +#endif };#ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {}
kernel/module.c +19 -0
@@ -1681,6 +1681,10 @@#ifdef CONFIG_IMMEDIATE immediateindex =find_sec (hdr, sechdrs, secstrings,"__immediate" );#endif +#ifdef CONFIG_MARKERS + markersindex =find_sec (hdr, sechdrs, secstrings,"__markers" ); + markersstringsindex =find_sec (hdr, sechdrs, secstrings,"__markers_strings" ); +#endif /* Don't keep modinfo section */ sechdrs[infoindex].sh_flags &= ~(unsigned long )SHF_ALLOC ;
@@ -1840,6 +1844,10 @@ sechdrs[immediateindex].sh_size / sizeof(*mod->immediates); }#endif +if (markersindex) + sechdrs[markersindex].sh_flags |=SHF_ALLOC ; +if (markersstringsindex) + sechdrs[markersstringsindex].sh_flags |=SHF_ALLOC ; mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;if (unusedcrcindex)
@@ -1881,6 +1889,13 @@if (err <0 ) goto cleanup; } +#ifdef CONFIG_MARKERS +if (markersindex) { + 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);
@@ -1899,6 +1914,10 @@add_kallsyms (mod, sechdrs, symindex, strindex, secstrings); + err =module_marker_update (mod); +if (err <0 ) + goto cleanup; +module_immediate_setup (mod); err =module_finalize (hdr, sechdrs, mod);
kernel/marker.c new file +491 -0
491 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -57,6 +57,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o obj-$(CONFIG_IMMEDIATE) += immediate.o +obj-$(CONFIG_MARKERS) += marker.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 3/5 Linux Kernel Markers - Add kconfig menus for the marker code
In reply to Mathieu DesnoyersWith the increasing complexity of today's user-space application and the wide deployment of SMP systems, the users need an increasing understanding of the behavior and performance of a system across multiple processes/different execution contexts/multiple CPUs. In applications such as large clusters (Google, IBM), video acquisition (Autodesk), embedded real-time systems (Wind River, Monta Vista, Sony) or sysadmin/programmer-type tasks (SystemTAP from Redhat), a tool that permits tracing of kernel-user space interaction becomes necessary.
Usage of such tools have been made to successfully pinpoint problems such as:
latency issues in a user-space video acquisition application, slowdown problems in large clusters due to a switch to a different filesystems with a different cache size, abnormal Linux scheduler latency (just to name a few that I have personally investigated).
The currently existing solutions does not give a system-wide overview of what
- and when - things are happening on the system. Ptracing a program works with few processes, but quickly becomes useless when it comes to keeping track of many processes.
Bugs occuring because of bad interaction of such complex systems can be very hard to find due to the fact that they occur rarely (sometimes once a week on hundreds of machines). One can therefore only hope at having the best conditions to statistically reproduce the bug while extracting information from the system. Some bugs have been successfully found at Google using their ktrace tracer only because they could enable it on production machines and therefore recreate the same context where the bug happened.
Therefore, it makes sense to offer an instrumentation set of the most relevant events occurring in the Linux that can have the smallest performance cost possible when not active while not requiring a reboot of a production system to activate. This is essentially what the markers are providing.
Since we cannot limit the growth of the Linux kernel, nor can we pre-determine each and every "interesting" instrumentation within each subsystem and driver, it is sensible to let this task to the persons who knows the best their code. Adding instrumentation should therefore be as easy as adding and maintaining a "printk" in the kernel code from the developer's point of view.
Towards a complete tracing mechanism in the Linux kernel, the markers are only one step forward. The following step is to connect probes to those markers that will record the tracing information in buffers exported to user-space, organized in timestamped "events". Probe callbacks are responsible for serializing the information passed as parameter to the markers (described by the format string) into the events. A control mechanism to activate/stop the tracing is required, as well as a daemon that maps the buffers to write them to disk or send them through the network.
Keeping track of the events also requires a centralized infrastructure : the idea is to assign a unique ID to each event so they can be later recognized in the trace. Keeping in mind that recording the complete instrumentation site name string for each event would be more that inefficient, assigning a numeric unique identifier makes sense.
Finally, support for gathering events coming from user-space, with a minimal performance impact, is very useful to see the interaction between the system's execution contexts.
The last steps are currently implemented in Linux Trace Toolkit Next Generation (LTTng).
The SystemTAP project could clearly benefit from such an infrastructure for tracing. In addition, they would be providing support for dynamic addition of kernel probes through breakpoints/jumps when possible, with the associated restrictions (accessing local variables, reentrancy, speed).
This marker infrastructure is a hook-callback mechanism. It is meant to have an impact as low as possible on the system performances when no callback (probe) is connected so markers (hooks) can be compiled into a production kernel without noticeable slowdown.
Why use the markers instead of kprobes?
The rationale behind this mechanism the following :
1 - It makes sense to have instrumentation (for tracing, profiling)
within the kernel source tree so that it can follow its evolution. Other options, such as kprobes, imply maintaining an external set of instrumentation that must be adapted to each kernel version. Although it may make sense for distributions, it is not well suited for kernel developers, since they rarely work on a major distribution image.
2 - kprobes, although being a very good attempt at providing a dynamic
hooking mechanism that has no impact when disabled, suffers from important limitations :
a - It cannot access local variables of a function at a particular
point within its body that will be consistent thorough the kernel versions without involving a lot of recurrent hair-pulling.
b - Kprobes is slow, since it involves going though a trap each time
a probe site is executed. Even though the djprobes project made a good effort to make things faster, it cannot currently instrument fully-preemptible kernels and does not solve (1), (2a) and (2c).
c - On the reentrancy side, going though a trap (thus playing with
interrupt enable/disable) and taking spinlocks are not suited to some code paths, i.e. :
kernel/lockdep.c, printk (within the lockdep_on()/lockdep_off()). It must be understood that some code paths interesting for instrumentation often present a particular reentrancy challenge.
Some more details :
The probe callback connection to its markers is done dynamically. A predicted branch (see the immediate values infrastructure) is used to skip the hook stack setup and function call when the marker is "disabled" (no probe is connected). Further optimizations can be implemented for each architecture to make this branch faster.
Instrumentation of a subsystem becomes therefore a straightforward task. One has to add instrumentation within the key locations of the kernel code in the following form :
trace_mark(subsystem_event, "%d %p", myint, myptr);
Jim Keniston <[email protected]> adds:
kprobes remains a vital foundation for SystemTap. But markers are attactive as an alternate source of trace/debug info. Here's why:
1. Markers will live in the kernel and presumably be kept up to date by the maintainers of the enclosing code. We have a growing set of tapsets (probe libraries), each of which "knows" the source code for a certain area of the kernel. Whenever the underlying kernel code changes (e.g., a function or one of its args disappears or is renamed), there's a chance that the tapset will become invalid until we bring it back in sync with the kernel. As you can imagine, maintaining tapsets separate from the kernel source is a maintenance headache. Markers could mitigate this.
2. Because the kernel code is highly optimized, the kernel's dwarf info doesn't always accurately reflect which variables have which values on which lines (sometimes even upon entry to a function). A marker is a way to ensure that values of interest are available to SystemTap at marked points.
3. Sometimes the overhead of a kprobe probepoint is too much (either in terms of time or locking) for the particular hotspot we want to probe.
In OLS2006 proceedings, vol. 1
http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
Frank C. Eigler, from SystemTAP, presents its "static probing markers" (pp. 261-268) in his paper "Problem Solving With Systemtap".
He explains the advantages :
"In exchange for this effort, systemtap marker-based probes are faster and
more precise than kprobes. The better precision comes from not having to covet the compiler's favours. Such fickle favours include retaining clean boundaries in the instruction stream between interesting statements, and precisely describing positions of variables in the stack frame. Since markers don't rely on debugging information, neither favour is required, and the compiler can channel its charms into unabated optimization. The speed advantage comes from using direct call instructions rather than int 3 breakpoints to dispatch to the systemtap handlers. We will see below just how big a difference this makes."
He does a comparison of his "simple" marker solution with kprobes (his simple solution looks like my generic markers, but with a major race condition). I also posted numbers about the markers performance impact a few months ago in the initial thread. I can dig into my emails to find them for you if you consider it important for the Changelog.
He concludes with :
"To the extent that is true, we propose that these groups consider using a
shared pool of static markers as the basic kernel-side instrumentation mechanism. If they prove to have as low dormant cost and as high active performance as initial experience suggests, perhaps this could motivate the various tracing efforts and kernel subsystem developers to finally join forces. Let's designate standard trace/probe points once and for all. Tracing backends can attach to these markers the same way systemtap would. There would be no need for them to maintain kernel patches any more. Let's think about it."
This patch:
Add Kconfig menus for the marker code.
---
arch/alpha/Kconfig | 2 ++ arch/arm/Kconfig | 2 ++ arch/arm26/Kconfig | 2 ++ arch/avr32/Kconfig.debug | 7 +++++++ arch/cris/Kconfig | 2 ++ arch/frv/Kconfig | 2 ++ arch/h8300/Kconfig | 2 ++ arch/i386/Kconfig | 2 ++ arch/ia64/Kconfig | 2 ++ arch/m32r/Kconfig | 2 ++ arch/m68k/Kconfig | 2 ++ arch/m68knommu/Kconfig | 2 ++ arch/mips/Kconfig | 2 ++ arch/parisc/Kconfig | 2 ++ arch/powerpc/Kconfig | 2 ++ arch/ppc/Kconfig | 2 ++ arch/s390/Kconfig | 2 ++ arch/sh/Kconfig | 2 ++ arch/sh64/Kconfig | 2 ++ arch/sparc/Kconfig | 2 ++ arch/sparc64/Kconfig | 2 ++ arch/um/Kconfig | 2 ++ arch/v850/Kconfig | 2 ++ arch/x86_64/Kconfig | 2 ++ arch/xtensa/Kconfig | 2 ++ kernel/Kconfig.marker | 7 +++++++ 26 files changed, 62 insertions(+)
arch/alpha/Kconfig +2 -0
@@ -657,6 +657,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/alpha/Kconfig.debug"
arch/arm/Kconfig +2 -0
@@ -1050,6 +1050,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/arm/Kconfig.debug"
arch/arm26/Kconfig +2 -0
@@ -248,6 +248,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/arm26/Kconfig.debug"
arch/cris/Kconfig +2 -0
@@ -202,6 +202,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/cris/Kconfig.debug"
arch/frv/Kconfig +2 -0
@@ -379,6 +379,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/frv/Kconfig.debug"
arch/h8300/Kconfig +2 -0
@@ -227,6 +227,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/h8300/Kconfig.debug"
arch/i386/Kconfig +2 -0
@@ -1237,6 +1237,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endif # INSTRUMENTATION source "arch/i386/Kconfig.debug"
arch/ia64/Kconfig +2 -0
@@ -596,6 +596,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/ia64/Kconfig.debug"
arch/m32r/Kconfig +2 -0
@@ -412,6 +412,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/m32r/Kconfig.debug"
arch/m68k/Kconfig +2 -0
@@ -683,6 +683,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/m68k/Kconfig.debug"
arch/m68knommu/Kconfig +2 -0
@@ -672,6 +672,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/m68knommu/Kconfig.debug"
arch/mips/Kconfig +2 -0
@@ -1961,6 +1961,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/mips/Kconfig.debug"
arch/parisc/Kconfig +2 -0
@@ -273,6 +273,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/parisc/Kconfig.debug"
arch/powerpc/Kconfig +2 -0
@@ -908,6 +908,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/powerpc/Kconfig.debug"
arch/ppc/Kconfig +2 -0
@@ -1457,6 +1457,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/ppc/Kconfig.debug"
arch/s390/Kconfig +2 -0
@@ -549,6 +549,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/s390/Kconfig.debug"
arch/sh/Kconfig +2 -0
@@ -725,6 +725,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/sh/Kconfig.debug"
arch/sh64/Kconfig +2 -0
@@ -288,6 +288,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/sh64/Kconfig.debug"
arch/sparc/Kconfig +2 -0
@@ -315,6 +315,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/sparc/Kconfig.debug"
arch/sparc64/Kconfig +2 -0
@@ -441,6 +441,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/sparc64/Kconfig.debug"
arch/um/Kconfig +2 -0
@@ -339,6 +339,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/um/Kconfig.debug"
arch/v850/Kconfig +2 -0
@@ -335,6 +335,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/v850/Kconfig.debug"
arch/x86_64/Kconfig +2 -0
@@ -795,6 +795,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/x86_64/Kconfig.debug"
arch/xtensa/Kconfig +2 -0
@@ -255,6 +255,8 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + endmenu source "arch/xtensa/Kconfig.debug"
kernel/Kconfig.marker new file +7 -0
@@ -0,0 +1,7 @@ +# Code markers configuration + +config MARKERS + bool "Activate markers" + help + Place an empty function call at each marker site. Can be + dynamically changed for a probe function.
arch/avr32/Kconfig.debug +7 -0
@@ -9,6 +9,9 @@ menu "Instrumentation Support" depends on EXPERIMENTAL +menu "Instrumentation Support" + depends on EXPERIMENTAL + config KPROBES bool "Kprobes" depends on DEBUG_KERNEL
@@ -21,6 +24,10 @@ source "kernel/Kconfig.immediate" +source "kernel/Kconfig.marker" + +endmenu + endmenu endmenu
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 4/5 Linux Kernel Markers - Documentation
In reply to Mathieu DesnoyersHere is some documentation explaining what is/how to use the Linux Kernel Markers.
---
Documentation/marker.txt | 249 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+)
Documentation/marker.txt new file +249 -0
@@ -0,0 +1,249 @@ + Using the Linux Kernel Markers + + Mathieu Desnoyers + + +This document introduces Linux Kernel Markers and their use. It provides +examples of how to insert markers in the kernel and connect probe functions to +them and provides some examples of probe functions. + + +* Purpose of markers + +A marker placed in your code provides a hook to call a function (probe) that +you can provide at runtime. A marker can be "on" (a probe is connected to it) +or "off" (no probe is attached). When a marker is "off" it has no +effect. When a marker is "on", the function you provide is called each +time the marker is executed, in the execution context of the +caller. When the function provided ends its execution, it returns to the +caller (continuing from the marker site). + +You can put markers at important locations in the code. Markers are +lightweight hooks that can pass an arbitrary number of parameters, +described in a printk-like format string, to the attached probe function. + +They can be used for tracing and performance accounting. + + +* Usage + +In order to use the macro trace_mark, you should include linux/marker.h. + +#include <linux/marker.h> + +Add, in your code : + +trace_mark(subsystem_event, "%d %s", someint, somestring); +Where : +- subsystem_event is an identifier unique to your event + - subsystem is the name of your subsystem. + - event is the name of the event to mark. +- "%d %s" is the formatted string for the serializer. +- someint is an integer. +- somestring is a char pointer. + +Connecting a function (probe) to a marker is done by providing a probe +(function to call) for the specific marker through marker_arm_probe(). It will +automatically connect the function and enable the marker site. Removing a probe +is done through marker_disarm_probe(). Probe removal is preempt-safe because +preemption is disabled around the probe call. See the "Probe example" section +below for a sample probe module. + +The marker mechanism supports inserting multiple instances of the same marker. +Markers can be put in inline functions, inlined static functions, and +unrolled loops. + +Note: It is safe to put markers within preempt-safe code : preempt_enable() +will not call the scheduler due to the tests in preempt_schedule(). + + +* Optimization for a given architecture + +One can implement optimized markers for a given architecture by replacing +asm-$ARCH/marker.h. + +The IF_* flags can be used to control the type of marker. See the +include/linux/immediate.h header for the list of flags. They can be specified as +the first parameter of the _trace_mark() macro, as in the following example, +which is safe with respect to lockdep.c (useful for marking lockdep.c and printk +functions). + +_trace_mark(IF_DEFAULT | ~IF_LOCKDEP, subsystem_eventb, MARK_NOARGS); + +Flag compatibility is checked before connecting the probe to the marker: the +right flags must be given to _marker_arm_probe(). + + +* Probe example + +You can build the kernel modules, probe-example.ko and marker-example.ko, +using the following Makefile: +------------------------------ CUT ------------------------------------- +obj-m := probe-example.o marker-example.o +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +default: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules +clean: + rm -f *.mod.c *.ko *.o +------------------------------ CUT ------------------------------------- +/* probe-example.c + * + * Connects two functions to marker call sites. + * + * (C) Copyright 2007 Mathieu Desnoyers <[email protected]> + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/marker.h> +#include <asm/atomic.h> + +struct probe_data { + const char *name; + const char *format; + marker_probe_func *probe_func; +}; + +void probe_subsystem_event(const struct __mark_marker_c *mdata, + const char *format, ...) +{ + va_list ap; + /* Declare args */ + unsigned int value; + const char *mystr; + + /* Assign args */ + va_start(ap, format); + value = va_arg(ap, typeof(value)); + mystr = va_arg(ap, typeof(mystr)); + + /* Call printk */ + printk("Value %u, string %s\n", value, mystr); + + /* or count, check rights, serialize data in a buffer */ + + va_end(ap); +} + +atomic_t eventb_count = ATOMIC_INIT(0); + +void probe_subsystem_eventb(const struct __mark_marker_c *mdata, + const char *format, ...) +{ + /* Increment counter */ + atomic_inc(&eventb_count); +} + +static struct probe_data probe_array[] = +{ + { .name = "subsystem_event", + .format = "%d %s", + .probe_func = probe_subsystem_event }, + { .name = "subsystem_eventb", + .format = MARK_NOARGS, + .probe_func = probe_subsystem_eventb }, +}; + +static int __init probe_init(void) +{ + int result; + int i; + + for (i = 0; i < ARRAY_SIZE(probe_array); i++) { + result = marker_arm_probe(probe_array[i].name, + probe_array[i].format, + probe_array[i].probe_func, &probe_array[i]); + if (result) + printk(KERN_INFO "Unable to register probe %s\n", + probe_array[i].name); + } + return 0; +} + +static void __exit probe_fini(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(probe_array); i++) { + marker_disarm_probe(probe_array[i].name); + } + printk("Number of event b : %u\n", atomic_read(&eventb_count)); +} + +module_init(probe_init); +module_exit(probe_fini); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("SUBSYSTEM Probe"); +------------------------------ CUT ------------------------------------- +/* marker-example.c + * + * Executes a marker when /proc/marker-example is opened. + * + * (C) Copyright 2007 Mathieu Desnoyers <[email protected]> + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include <linux/module.h> +#include <linux/marker.h> +#include <linux/sched.h> +#include <linux/proc_fs.h> + +struct proc_dir_entry *pentry_example = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + int i; + + trace_mark(subsystem_event, "%d %s", 123, "example string"); + for (i=0; i<10; i++) { + trace_mark(subsystem_eventb, MARK_NOARGS); + } + return -EPERM; +} + +static struct file_operations mark_ops = { + .open = my_open, +}; + +static int example_init(void) +{ + printk(KERN_ALERT "example init\n"); + pentry_example = create_proc_entry("marker-example", 0444, NULL); + if (pentry_example) + pentry_example->proc_fops = &mark_ops; + else + return -EPERM; + return 0; +} + +static void example_exit(void) +{ + printk(KERN_ALERT "example exit\n"); + remove_proc_entry("marker-example", NULL); +} + +module_init(example_init) +module_exit(example_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Linux Trace Toolkit example"); +------------------------------ CUT ------------------------------------- +Sequence of operations : (as root) +make +insmod marker-example.ko +insmod probe-example.ko + (it is important to load the probe after the marked code) +cat /proc/marker-example (returns an expected error) +rmmod marker-example probe-example +dmesg +------------------------------ CUT -------------------------------------
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
PATCH 5/5 Port of blktrace to the Linux Kernel Markers.
In reply to Mathieu DesnoyersHere is a proof of concept patch, for demonstration purpose, of moving blktrace to the markers.
A few remarks : this patch has the positive effect of removing some code from the block io tracing hot paths, minimizing the i-cache impact in a system where the io tracing is compiled in but inactive.
It also moves the blk tracing code from a header (and therefore from the body of the instrumented functions) to a separate C file.
There, as soon as one device has to be traced, every devices have to fall into the tracing function call. This is slower than the previous inline function which tested the condition quickly. If it becomes a show stopper, it could be fixed by having the possibility to test a supplementary condition, dependant of the marker context, at the marker site, just after the enable/disable test.
It does not make the code smaller, since I left all the specialized tracing functions for requests, bio, generic, remap, which would go away once a generic infrastructure is in place to serialize the information passed to the marker. This is mostly why I consider it a proof a concept.
---
block/Kconfig | 1 block/blktrace.c | 281 ++++++++++++++++++++++++++++++++++++++++++- block/elevator.c | 6 block/ll_rw_blk.c | 27 ++-- drivers/block/cciss.c | 4 drivers/md/dm.c | 14 +- fs/bio.c | 4 include/linux/blktrace_api.h | 146 +--------------------- mm/bounce.c | 4 mm/highmem.c | 2 10 files changed, 322 insertions(+), 167 deletions(-)
block/elevator.c +3 -3
@@ -32,7 +32,7 @@#include <linux/init.h> #include <linux/compiler.h> #include <linux/delay.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <linux/hash.h> #include <asm/uaccess.h>
@@ -547,7 +547,7 @@unsigned ordseq;int unplug_it =1 ; -blk_add_trace_rq (q, rq,BLK_TA_INSERT ); +trace_mark (blk_request_insert,"%p %p" , q, rq); rq->q = q;
@@ -726,7 +726,7 @@* not be passed by new incoming requests */ rq->cmd_flags |=REQ_STARTED ; -blk_add_trace_rq (q, rq,BLK_TA_ISSUE ); +trace_mark (blk_request_issue,"%p %p" , q, rq); }if (!q->boundary_rq || q->boundary_rq == rq) {
block/ll_rw_blk.c +14 -13
@@ -28,6 +28,7 @@#include <linux/task_io_accounting_ops.h> #include <linux/interrupt.h> #include <linux/cpu.h> +#include <linux/marker.h> #include <linux/blktrace_api.h> #include <linux/fault-inject.h>
@@ -1551,7 +1552,7 @@if (!test_and_set_bit (QUEUE_FLAG_PLUGGED , &q->queue_flags)) {mod_timer (&q->unplug_timer, jiffies + q->unplug_delay); -blk_add_trace_generic (q,NULL ,0 ,BLK_TA_PLUG ); +trace_mark (blk_plug_device,"%p %p %d" , q,NULL ,0 ); } }
@@ -1617,7 +1618,7 @@* devices don't necessarily have an ->unplug_fn defined */ if (q->unplug_fn) { -blk_add_trace_pdu_int (q,BLK_TA_UNPLUG_IO ,NULL , +trace_mark (blk_pdu_unplug_io,"%p %p %d" , q,NULL , q->rq.count[READ ] + q->rq.count[WRITE ]); q->unplug_fn (q);
@@ -1628,7 +1629,7 @@ {request_queue_t *q =container_of (work, request_queue_t, unplug_work); -blk_add_trace_pdu_int (q,BLK_TA_UNPLUG_IO ,NULL , +trace_mark (blk_pdu_unplug_io,"%p %p %d" , q,NULL , q->rq.count[READ ] + q->rq.count[WRITE ]); q->unplug_fn (q);
@@ -1638,7 +1639,7 @@ {request_queue_t *q = (request_queue_t *)data; -blk_add_trace_pdu_int (q,BLK_TA_UNPLUG_TIMER ,NULL , +trace_mark (blk_pdu_unplug_timer,"%p %p %d" , q,NULL , q->rq.count[READ ] + q->rq.count[WRITE ]);kblockd_schedule_work (&q->unplug_work);
@@ -2150,7 +2151,7 @@rq_init (q, rq); -blk_add_trace_generic (q, bio, rw,BLK_TA_GETRQ ); +trace_mark (blk_get_request,"%p %p %d" , q, bio, rw); out:return rq; }
@@ -2180,7 +2181,7 @@if (!rq) {struct io_context *ioc; -blk_add_trace_generic (q, bio, rw,BLK_TA_SLEEPRQ ); +trace_mark (blk_sleep_request,"%p %p %d" , q, bio, rw);__generic_unplug_device (q);spin_unlock_irq (q->queue_lock);
@@ -2254,7 +2255,7 @@*/ void blk_requeue_request (request_queue_t *q,struct request *rq) { -blk_add_trace_rq (q, rq,BLK_TA_REQUEUE ); +trace_mark (blk_requeue,"%p %p" , q, rq);if (blk_rq_tagged (rq))blk_queue_end_tag (q, rq);
@@ -2940,7 +2941,7 @@if (!ll_back_merge_fn (q, req, bio))break ; -blk_add_trace_bio (q, bio,BLK_TA_BACKMERGE ); +trace_mark (blk_bio_backmerge,"%p %p" , q, bio); req->biotail->bi_next = bio; req->biotail = bio;
@@ -2957,7 +2958,7 @@if (!ll_front_merge_fn (q, req, bio))break ; -blk_add_trace_bio (q, bio,BLK_TA_FRONTMERGE ); +trace_mark (blk_bio_frontmerge,"%p %p" , q, bio); bio->bi_next = req->bio; req->bio = bio;
@@ -3187,10 +3188,10 @@blk_partition_remap (bio);if (old_sector !=-1 ) -blk_add_trace_remap (q, bio, old_dev, bio->bi_sector, - old_sector); +trace_mark (blk_remap,"%p %p %u %llu %llu" , q, bio, old_dev, + (u64 )bio->bi_sector, (u64 )old_sector); -blk_add_trace_bio (q, bio,BLK_TA_QUEUE ); +trace_mark (blk_bio_queue,"%p %p" , q, bio); old_sector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev;
@@ -3383,7 +3384,7 @@int total_bytes, bio_nbytes, error, next_idx =0 ;struct bio *bio; -blk_add_trace_rq (req->q, req,BLK_TA_COMPLETE ); +trace_mark (blk_request_complete,"%p %p" , req->q, req);/* * extend uptodate bool to allow < 0 value to be direct io error
block/Kconfig +1 -0
@@ -32,6 +32,7 @@ depends on SYSFS select RELAY select DEBUG_FS + select MARKERS help Say Y here, if you want to be able to trace the block layer actions on a given queue. Tracing allows you to see any traffic happening
block/blktrace.c +279 -2
318 lines not on this page · raw message
include/linux/blktrace_api.h +11 -135
166 lines not on this page · raw message
mm/bounce.c +2 -2
@@ -13,7 +13,7 @@#include <linux/init.h> #include <linux/hash.h> #include <linux/highmem.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <asm/tlbflush.h> #define POOL_SIZE 64
@@ -237,7 +237,7 @@if (!bio)return ; -blk_add_trace_bio (q, *bio_orig,BLK_TA_BOUNCE ); +trace_mark (blk_bio_bounce,"%p %p" , q, *bio_orig);/* * at least one page was bounced, fill in possible non-highmem
mm/highmem.c +1 -1
@@ -26,7 +26,7 @@#include <linux/init.h> #include <linux/hash.h> #include <linux/highmem.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <asm/tlbflush.h> /*
fs/bio.c +2 -2
@@ -25,7 +25,7 @@#include <linux/module.h> #include <linux/mempool.h> #include <linux/workqueue.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <scsi/sg.h> /* for struct sg_iovec */ #define BIO_POOL_SIZE 2
@@ -1081,7 +1081,7 @@if (!bp)return bp; -blk_add_trace_pdu_int (bdev_get_queue (bi->bi_bdev),BLK_TA_SPLIT , bi, +trace_mark (blk_pdu_split,"%p %p %d" ,bdev_get_queue (bi->bi_bdev), bi, bi->bi_sector + first_sectors);BUG_ON (bi->bi_vcnt !=1 );
drivers/block/cciss.c +2 -2
@@ -37,7 +37,7 @@#include <linux/hdreg.h> #include <linux/spinlock.h> #include <linux/compat.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <asm/uaccess.h> #include <asm/io.h>
@@ -2502,7 +2502,7 @@ } cmd->rq->data_len =0 ; cmd->rq->completion_data = cmd; -blk_add_trace_rq (cmd->rq->q, cmd->rq,BLK_TA_COMPLETE ); +trace_mark (blk_request_complete,"%p %p" , cmd->rq->q, cmd->rq);blk_complete_request (cmd->rq); }
drivers/md/dm.c +7 -7
@@ -19,7 +19,7 @@#include <linux/slab.h> #include <linux/idr.h> #include <linux/hdreg.h> -#include <linux/blktrace_api.h> +#include <linux/marker.h> #include <linux/smp_lock.h> #define DM_MSG_PREFIX "core"
@@ -483,8 +483,8 @@wake_up (&io->md->wait);if (io->error !=DM_ENDIO_REQUEUE ) { -blk_add_trace_bio (io->md->queue, io->bio, -BLK_TA_COMPLETE ); +trace_mark (blk_request_complete,"%p %p" , + io->md->queue, io->bio);bio_endio (io->bio, io->bio->bi_size, io->error); }
@@ -580,10 +580,10 @@ r = ti->type->map (ti, clone, &tio->info);if (r ==DM_MAPIO_REMAPPED ) {/* the bio has been remapped so dispatch it */ - -blk_add_trace_remap (bdev_get_queue (clone->bi_bdev), clone, - tio->io->bio->bi_bdev->bd_dev, sector, - clone->bi_sector); +trace_mark (blk_remap,"%p %p %u %llu %llu" , +bdev_get_queue (clone->bi_bdev), clone, + (u64 )tio->io->bio->bi_bdev->bd_dev, (u64 )sector, + (u64 )clone->bi_sector);generic_make_request (clone); }else if (r <0 || r ==DM_MAPIO_REQUEUE ) {
Signature · 3 lines
Mathieu Desnoyers Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68