OProfile update
Subsystems (2)
PATCH 1/5 OProfile update
The five patches here change the following files :
Documentation/kernel-parameters.txt | 3 ++ drivers/oprofile/buffer_sync.c | 49 ++++++++++++++++++++++++++---------- drivers/oprofile/cpu_buffer.c | 6 +--- drivers/oprofile/event_buffer.h | 1 drivers/oprofile/oprof.c | 25 +++++++++++++----- fs/dcookies.c | 6 ++++ 6 files changed, 67 insertions(+), 23 deletions(-)
please apply
john
My previous fix was incomplete, we could get the same thing happening on the init-failure path. Fix that.
drivers/oprofile/buffer_sync.c +10 -4
@@ -127,6 +127,14 @@ }; +static void end_sync_timer (void ) +{ +del_timer_sync (&sync_timer); +/* timer might have queued work, make sure it's completed. */ +flush_scheduled_work (); +} + +int sync_start (void ) {int err;
@@ -158,7 +166,7 @@ out2:profile_event_unregister (EXIT_TASK , &exit_task_nb); out1: -del_timer_sync (&sync_timer); +end_sync_timer (); goto out; }
@@ -169,9 +177,7 @@profile_event_unregister (EXIT_TASK , &exit_task_nb);profile_event_unregister (EXIT_MMAP , &exit_mmap_nb);profile_event_unregister (EXEC_UNMAP , &exec_unmap_nb); -del_timer_sync (&sync_timer); -/* timer might have queued work, make sure it's completed. */ -flush_scheduled_work (); +end_sync_timer (); }
PATCH 2/5 OProfile update
The code that attempts to reset last_task and in_kernel has a race against samples appearing during the handling of the buffers, that causes a small number of mis-attribution of samples. Closing the window is non-obvious, and not worth it, so we just make it smaller. Even without the patch, there seem to be few such "bad" samples because its effects are mitigated on a switch into userspace or a task switch.
drivers/oprofile/buffer_sync.c +18 -6
@@ -366,12 +377,26 @@ } -/* compute number of filled slots in cpu_buffer queue */ -static unsigned long nr_filled_slots (struct oprofile_cpu_buffer * b) +/* "acquire" as many cpu buffer slots as we can */ +static unsigned long get_slots (struct oprofile_cpu_buffer * b) {unsigned long head = b->head_pos;unsigned long tail = b->tail_pos; +/* +* Subtle. This resets the persistent last_task +* and in_kernel values used for switching notes. +* BUT, there is a small window between reading +* head_pos, and this call, that means samples +* can appear at the new head position, but not +* be prefixed with the notes for switching +* kernel mode or a task switch. This small hole +* can lead to mis-attribution or samples where +* we don't know if it's in the kernel or not, +* at the start of an event buffer. +*/ +cpu_buffer_reset (b); +if (head >= tail)return head - tail;
@@ -408,9 +433,9 @@/* Remember, only we can modify tail_pos */ -unsigned long const available_elements =nr_filled_slots (cpu_buf); +unsigned long const available =get_slots (cpu_buf); -for (i=0 ; i < available_elements; ++i) { +for (i=0 ; i < available; ++i) {struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];if (is_ctx_switch (s->eip)) {
@@ -435,8 +460,6 @@increment_tail (cpu_buf); }release_mm (mm); - -cpu_buffer_reset (cpu_buf); }
PATCH 4/5 OProfile update
In reply to John LevonFix a stale comment.
drivers/oprofile/cpu_buffer.c +2 -4
@@ -168,10 +168,8 @@ } -/* resets the cpu buffer to a sane state - should be called with -* cpu_buf->int_lock held -*/ -void cpu_buffer_reset (struct oprofile_cpu_buffer *cpu_buf) +/* Resets the cpu buffer to a sane state. */ +void cpu_buffer_reset (struct oprofile_cpu_buffer * cpu_buf) {/* reset these to invalid values; the next sample * collected will populate the buffer with proper
PATCH 5/5 OProfile update
d_path() can return -ENAMETOOLONG these days. Pass it upstream.
fs/dcookies.c +6 -0
@@ -175,6 +175,11 @@/* FIXME: (deleted) ? */ path =d_path (dcs->dentry, dcs->vfsmnt, kbuf,PAGE_SIZE ); +if (IS_ERR (path)) { + err =PTR_ERR (path); + goto out_free; + } + err = -ERANGE ; pathlen = kbuf +PAGE_SIZE - path;
@@ -184,6 +189,7 @@ err = -EFAULT ; } +out_free:kfree (kbuf); out:up (&dcookie_sem);
PATCH 3/5 OProfile update
In reply to John LevonA patch mostly by Will Cohen, adding a parameter to OProfile to over-ride use of the perfctr hardware. Useful for testing and a host of other things.
Documentation/kernel-parameters.txt +3 -0
@@ -652,6 +652,9 @@ opl3sa2= [HW,OSS] Format: <io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple] + oprofile.timer= [HW] + Use timer interrupt instead of performance counters + optcd= [HW,CD] Format: <io>
drivers/oprofile/oprof.c +19 -6
@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/init.h> #include <linux/oprofile.h> +#include <linux/moduleparam.h> #include <asm/semaphore.h> #include "oprof.h"
@@ -24,6 +25,12 @@static unsigned long is_setup;static DECLARE_MUTEX (start_sem); +/* timer +0 - use performance monitoring hardware if available +1 - use the timer int mechanism regardless +*/ +static int timer =0 ; +int oprofile_setup (void ) {int err;
@@ -124,13 +131,16 @@static int __init oprofile_init (void ) { -int err; +int err = -ENODEV ; + +if (!timer) { +/* Architecture must fill in the interrupt ops and the +* logical CPU type, or we can fall back to the timer +* interrupt profiler. +*/ + err =oprofile_arch_init (&oprofile_ops); + } -/* Architecture must fill in the interrupt ops and the -* logical CPU type, or we can fall back to the timer -* interrupt profiler. -*/ - err =oprofile_arch_init (&oprofile_ops);if (err == -ENODEV ) {timer_init (&oprofile_ops); err =0 ;
@@ -163,6 +173,9 @@module_init (oprofile_init);module_exit (oprofile_exit); + +module_param_named (timer, timer, int,0644 ); +MODULE_PARM_DESC (timer,"force use of timer interrupt" );MODULE_LICENSE ("GPL" );MODULE_AUTHOR ("John Levon <[email protected]>" );