aboutsummaryrefslogtreecommitdiff
path: root/drivers/oprofile
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/oprofile')
-rw-r--r--drivers/oprofile/buffer_sync.c17
-rw-r--r--drivers/oprofile/cpu_buffer.c11
-rw-r--r--drivers/oprofile/nmi_timer_int.c23
-rw-r--r--drivers/oprofile/oprof.h3
-rw-r--r--drivers/oprofile/oprofile_files.c26
-rw-r--r--drivers/oprofile/oprofile_perf.c39
-rw-r--r--drivers/oprofile/oprofile_stats.c24
-rw-r--r--drivers/oprofile/oprofile_stats.h3
-rw-r--r--drivers/oprofile/oprofilefs.c53
-rw-r--r--drivers/oprofile/timer_int.c4
10 files changed, 98 insertions, 105 deletions
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index f34b5b29fb9..d93b2b6b1f7 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -216,7 +216,7 @@ static inline unsigned long fast_get_dcookie(struct path *path)
}
-/* Look up the dcookie for the task's first VM_EXECUTABLE mapping,
+/* Look up the dcookie for the task's mm->exe_file,
* which corresponds loosely to "application name". This is
* not strictly necessary but allows oprofile to associate
* shared-library samples with particular applications
@@ -224,21 +224,10 @@ static inline unsigned long fast_get_dcookie(struct path *path)
static unsigned long get_exec_dcookie(struct mm_struct *mm)
{
unsigned long cookie = NO_COOKIE;
- struct vm_area_struct *vma;
-
- if (!mm)
- goto out;
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (!vma->vm_file)
- continue;
- if (!(vma->vm_flags & VM_EXECUTABLE))
- continue;
- cookie = fast_get_dcookie(&vma->vm_file->f_path);
- break;
- }
+ if (mm && mm->exe_file)
+ cookie = fast_get_dcookie(&mm->exe_file->f_path);
-out:
return cookie;
}
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index b8ef8ddcc29..8aa73fac6ad 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -451,14 +451,9 @@ static void wq_sync_buffer(struct work_struct *work)
{
struct oprofile_cpu_buffer *b =
container_of(work, struct oprofile_cpu_buffer, work.work);
- if (b->cpu != smp_processor_id()) {
- printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n",
- smp_processor_id(), b->cpu);
-
- if (!cpu_online(b->cpu)) {
- cancel_delayed_work(&b->work);
- return;
- }
+ if (b->cpu != smp_processor_id() && !cpu_online(b->cpu)) {
+ cancel_delayed_work(&b->work);
+ return;
}
sync_buffer(b->cpu);
diff --git a/drivers/oprofile/nmi_timer_int.c b/drivers/oprofile/nmi_timer_int.c
index 76f1c9357f3..9559829fb23 100644
--- a/drivers/oprofile/nmi_timer_int.c
+++ b/drivers/oprofile/nmi_timer_int.c
@@ -108,8 +108,8 @@ static void nmi_timer_shutdown(void)
struct perf_event *event;
int cpu;
- get_online_cpus();
- unregister_cpu_notifier(&nmi_timer_cpu_nb);
+ cpu_notifier_register_begin();
+ __unregister_cpu_notifier(&nmi_timer_cpu_nb);
for_each_possible_cpu(cpu) {
event = per_cpu(nmi_timer_events, cpu);
if (!event)
@@ -119,7 +119,7 @@ static void nmi_timer_shutdown(void)
perf_event_release_kernel(event);
}
- put_online_cpus();
+ cpu_notifier_register_done();
}
static int nmi_timer_setup(void)
@@ -132,20 +132,23 @@ static int nmi_timer_setup(void)
do_div(period, HZ);
nmi_timer_attr.sample_period = period;
- get_online_cpus();
- err = register_cpu_notifier(&nmi_timer_cpu_nb);
+ cpu_notifier_register_begin();
+ err = __register_cpu_notifier(&nmi_timer_cpu_nb);
if (err)
goto out;
+
/* can't attach events to offline cpus: */
for_each_online_cpu(cpu) {
err = nmi_timer_start_cpu(cpu);
- if (err)
- break;
+ if (err) {
+ cpu_notifier_register_done();
+ nmi_timer_shutdown();
+ return err;
+ }
}
- if (err)
- nmi_timer_shutdown();
+
out:
- put_online_cpus();
+ cpu_notifier_register_done();
return err;
}
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index d32ef816337..d5412060ab0 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -30,10 +30,9 @@ extern struct oprofile_operations oprofile_ops;
extern unsigned long oprofile_started;
extern unsigned long oprofile_backtrace_depth;
-struct super_block;
struct dentry;
-void oprofile_create_files(struct super_block *sb, struct dentry *root);
+void oprofile_create_files(struct dentry *root);
int oprofile_timer_init(struct oprofile_operations *ops);
#ifdef CONFIG_OPROFILE_NMI_TIMER
int op_nmi_timer_init(struct oprofile_operations *ops);
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index 84a208dbed9..ee2cfce358b 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -175,7 +175,7 @@ static const struct file_operations dump_fops = {
.llseek = noop_llseek,
};
-void oprofile_create_files(struct super_block *sb, struct dentry *root)
+void oprofile_create_files(struct dentry *root)
{
/* reinitialize default values */
oprofile_buffer_size = BUFFER_SIZE_DEFAULT;
@@ -183,19 +183,19 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root)
oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT;
oprofile_time_slice = msecs_to_jiffies(TIME_SLICE_DEFAULT);
- oprofilefs_create_file(sb, root, "enable", &enable_fops);
- oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
- oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
- oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size);
- oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed);
- oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &oprofile_cpu_buffer_size);
- oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops);
- oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops);
- oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops);
+ oprofilefs_create_file(root, "enable", &enable_fops);
+ oprofilefs_create_file_perm(root, "dump", &dump_fops, 0666);
+ oprofilefs_create_file(root, "buffer", &event_buffer_fops);
+ oprofilefs_create_ulong(root, "buffer_size", &oprofile_buffer_size);
+ oprofilefs_create_ulong(root, "buffer_watershed", &oprofile_buffer_watershed);
+ oprofilefs_create_ulong(root, "cpu_buffer_size", &oprofile_cpu_buffer_size);
+ oprofilefs_create_file(root, "cpu_type", &cpu_type_fops);
+ oprofilefs_create_file(root, "backtrace_depth", &depth_fops);
+ oprofilefs_create_file(root, "pointer_size", &pointer_size_fops);
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
- oprofilefs_create_file(sb, root, "time_slice", &timeout_fops);
+ oprofilefs_create_file(root, "time_slice", &timeout_fops);
#endif
- oprofile_create_stats_files(sb, root);
+ oprofile_create_stats_files(root);
if (oprofile_ops.create_files)
- oprofile_ops.create_files(sb, root);
+ oprofile_ops.create_files(root);
}
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index efc4b7f308c..d5b2732b1b8 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -1,5 +1,6 @@
/*
* Copyright 2010 ARM Ltd.
+ * Copyright 2012 Advanced Micro Devices, Inc., Robert Richter
*
* Perf-events backend for OProfile.
*/
@@ -25,7 +26,7 @@ static int oprofile_perf_enabled;
static DEFINE_MUTEX(oprofile_perf_mutex);
static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[NR_CPUS];
+static DEFINE_PER_CPU(struct perf_event **, perf_events);
static int num_counters;
/*
@@ -38,7 +39,7 @@ static void op_overflow_handler(struct perf_event *event,
u32 cpu = smp_processor_id();
for (id = 0; id < num_counters; ++id)
- if (perf_events[cpu][id] == event)
+ if (per_cpu(perf_events, cpu)[id] == event)
break;
if (id != num_counters)
@@ -74,7 +75,7 @@ static int op_create_counter(int cpu, int event)
{
struct perf_event *pevent;
- if (!counter_config[event].enabled || perf_events[cpu][event])
+ if (!counter_config[event].enabled || per_cpu(perf_events, cpu)[event])
return 0;
pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
@@ -91,18 +92,18 @@ static int op_create_counter(int cpu, int event)
return -EBUSY;
}
- perf_events[cpu][event] = pevent;
+ per_cpu(perf_events, cpu)[event] = pevent;
return 0;
}
static void op_destroy_counter(int cpu, int event)
{
- struct perf_event *pevent = perf_events[cpu][event];
+ struct perf_event *pevent = per_cpu(perf_events, cpu)[event];
if (pevent) {
perf_event_release_kernel(pevent);
- perf_events[cpu][event] = NULL;
+ per_cpu(perf_events, cpu)[event] = NULL;
}
}
@@ -137,7 +138,7 @@ static void op_perf_stop(void)
op_destroy_counter(cpu, event);
}
-static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root)
+static int oprofile_perf_create_files(struct dentry *root)
{
unsigned int i;
@@ -146,13 +147,13 @@ static int oprofile_perf_create_files(struct super_block *sb, struct dentry *roo
char buf[4];
snprintf(buf, sizeof buf, "%d", i);
- dir = oprofilefs_mkdir(sb, root, buf);
- oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
- oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
- oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
- oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
- oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
- oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+ dir = oprofilefs_mkdir(root, buf);
+ oprofilefs_create_ulong(dir, "enabled", &counter_config[i].enabled);
+ oprofilefs_create_ulong(dir, "event", &counter_config[i].event);
+ oprofilefs_create_ulong(dir, "count", &counter_config[i].count);
+ oprofilefs_create_ulong(dir, "unit_mask", &counter_config[i].unit_mask);
+ oprofilefs_create_ulong(dir, "kernel", &counter_config[i].kernel);
+ oprofilefs_create_ulong(dir, "user", &counter_config[i].user);
}
return 0;
@@ -257,12 +258,12 @@ void oprofile_perf_exit(void)
for_each_possible_cpu(cpu) {
for (id = 0; id < num_counters; ++id) {
- event = perf_events[cpu][id];
+ event = per_cpu(perf_events, cpu)[id];
if (event)
perf_event_release_kernel(event);
}
- kfree(perf_events[cpu]);
+ kfree(per_cpu(perf_events, cpu));
}
kfree(counter_config);
@@ -277,8 +278,6 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
if (ret)
return ret;
- memset(&perf_events, 0, sizeof(perf_events));
-
num_counters = perf_num_counters();
if (num_counters <= 0) {
pr_info("oprofile: no performance counters\n");
@@ -298,9 +297,9 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
}
for_each_possible_cpu(cpu) {
- perf_events[cpu] = kcalloc(num_counters,
+ per_cpu(perf_events, cpu) = kcalloc(num_counters,
sizeof(struct perf_event *), GFP_KERNEL);
- if (!perf_events[cpu]) {
+ if (!per_cpu(perf_events, cpu)) {
pr_info("oprofile: failed to allocate %d perf events "
"for cpu %d\n", num_counters, cpu);
ret = -ENOMEM;
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index 917d28ebeac..59659cea458 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -38,7 +38,7 @@ void oprofile_reset_stats(void)
}
-void oprofile_create_stats_files(struct super_block *sb, struct dentry *root)
+void oprofile_create_stats_files(struct dentry *root)
{
struct oprofile_cpu_buffer *cpu_buf;
struct dentry *cpudir;
@@ -46,39 +46,39 @@ void oprofile_create_stats_files(struct super_block *sb, struct dentry *root)
char buf[10];
int i;
- dir = oprofilefs_mkdir(sb, root, "stats");
+ dir = oprofilefs_mkdir(root, "stats");
if (!dir)
return;
for_each_possible_cpu(i) {
cpu_buf = &per_cpu(op_cpu_buffer, i);
snprintf(buf, 10, "cpu%d", i);
- cpudir = oprofilefs_mkdir(sb, dir, buf);
+ cpudir = oprofilefs_mkdir(dir, buf);
/* Strictly speaking access to these ulongs is racy,
* but we can't simply lock them, and they are
* informational only.
*/
- oprofilefs_create_ro_ulong(sb, cpudir, "sample_received",
+ oprofilefs_create_ro_ulong(cpudir, "sample_received",
&cpu_buf->sample_received);
- oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
+ oprofilefs_create_ro_ulong(cpudir, "sample_lost_overflow",
&cpu_buf->sample_lost_overflow);
- oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted",
+ oprofilefs_create_ro_ulong(cpudir, "backtrace_aborted",
&cpu_buf->backtrace_aborted);
- oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip",
+ oprofilefs_create_ro_ulong(cpudir, "sample_invalid_eip",
&cpu_buf->sample_invalid_eip);
}
- oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
+ oprofilefs_create_ro_atomic(dir, "sample_lost_no_mm",
&oprofile_stats.sample_lost_no_mm);
- oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mapping",
+ oprofilefs_create_ro_atomic(dir, "sample_lost_no_mapping",
&oprofile_stats.sample_lost_no_mapping);
- oprofilefs_create_ro_atomic(sb, dir, "event_lost_overflow",
+ oprofilefs_create_ro_atomic(dir, "event_lost_overflow",
&oprofile_stats.event_lost_overflow);
- oprofilefs_create_ro_atomic(sb, dir, "bt_lost_no_mapping",
+ oprofilefs_create_ro_atomic(dir, "bt_lost_no_mapping",
&oprofile_stats.bt_lost_no_mapping);
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
- oprofilefs_create_ro_atomic(sb, dir, "multiplex_counter",
+ oprofilefs_create_ro_atomic(dir, "multiplex_counter",
&oprofile_stats.multiplex_counter);
#endif
}
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h
index 38b6fc02898..1fc622bd183 100644
--- a/drivers/oprofile/oprofile_stats.h
+++ b/drivers/oprofile/oprofile_stats.h
@@ -25,10 +25,9 @@ extern struct oprofile_stat_struct oprofile_stats;
/* reset all stats to zero */
void oprofile_reset_stats(void);
-struct super_block;
struct dentry;
/* create the stats/ dir */
-void oprofile_create_stats_files(struct super_block *sb, struct dentry *root);
+void oprofile_create_stats_files(struct dentry *root);
#endif /* OPROFILE_STATS_H */
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 849357c1045..3f493459378 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -132,40 +132,44 @@ static const struct file_operations ulong_ro_fops = {
};
-static int __oprofilefs_create_file(struct super_block *sb,
- struct dentry *root, char const *name, const struct file_operations *fops,
- int perm, void *priv)
+static int __oprofilefs_create_file(struct dentry *root, char const *name,
+ const struct file_operations *fops, int perm, void *priv)
{
struct dentry *dentry;
struct inode *inode;
+ mutex_lock(&root->d_inode->i_mutex);
dentry = d_alloc_name(root, name);
- if (!dentry)
+ if (!dentry) {
+ mutex_unlock(&root->d_inode->i_mutex);
return -ENOMEM;
- inode = oprofilefs_get_inode(sb, S_IFREG | perm);
+ }
+ inode = oprofilefs_get_inode(root->d_sb, S_IFREG | perm);
if (!inode) {
dput(dentry);
+ mutex_unlock(&root->d_inode->i_mutex);
return -ENOMEM;
}
inode->i_fop = fops;
+ inode->i_private = priv;
d_add(dentry, inode);
- dentry->d_inode->i_private = priv;
+ mutex_unlock(&root->d_inode->i_mutex);
return 0;
}
-int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root,
+int oprofilefs_create_ulong(struct dentry *root,
char const *name, unsigned long *val)
{
- return __oprofilefs_create_file(sb, root, name,
+ return __oprofilefs_create_file(root, name,
&ulong_fops, 0644, val);
}
-int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root,
+int oprofilefs_create_ro_ulong(struct dentry *root,
char const *name, unsigned long *val)
{
- return __oprofilefs_create_file(sb, root, name,
+ return __oprofilefs_create_file(root, name,
&ulong_ro_fops, 0444, val);
}
@@ -184,45 +188,49 @@ static const struct file_operations atomic_ro_fops = {
};
-int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
+int oprofilefs_create_ro_atomic(struct dentry *root,
char const *name, atomic_t *val)
{
- return __oprofilefs_create_file(sb, root, name,
+ return __oprofilefs_create_file(root, name,
&atomic_ro_fops, 0444, val);
}
-int oprofilefs_create_file(struct super_block *sb, struct dentry *root,
+int oprofilefs_create_file(struct dentry *root,
char const *name, const struct file_operations *fops)
{
- return __oprofilefs_create_file(sb, root, name, fops, 0644, NULL);
+ return __oprofilefs_create_file(root, name, fops, 0644, NULL);
}
-int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root,
+int oprofilefs_create_file_perm(struct dentry *root,
char const *name, const struct file_operations *fops, int perm)
{
- return __oprofilefs_create_file(sb, root, name, fops, perm, NULL);
+ return __oprofilefs_create_file(root, name, fops, perm, NULL);
}
-struct dentry *oprofilefs_mkdir(struct super_block *sb,
- struct dentry *root, char const *name)
+struct dentry *oprofilefs_mkdir(struct dentry *parent, char const *name)
{
struct dentry *dentry;
struct inode *inode;
- dentry = d_alloc_name(root, name);
- if (!dentry)
+ mutex_lock(&parent->d_inode->i_mutex);
+ dentry = d_alloc_name(parent, name);
+ if (!dentry) {
+ mutex_unlock(&parent->d_inode->i_mutex);
return NULL;
- inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
+ }
+ inode = oprofilefs_get_inode(parent->d_sb, S_IFDIR | 0755);
if (!inode) {
dput(dentry);
+ mutex_unlock(&parent->d_inode->i_mutex);
return NULL;
}
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
d_add(dentry, inode);
+ mutex_unlock(&parent->d_inode->i_mutex);
return dentry;
}
@@ -246,7 +254,7 @@ static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent)
if (!sb->s_root)
return -ENOMEM;
- oprofile_create_files(sb, sb->s_root);
+ oprofile_create_files(sb->s_root);
// FIXME: verify kill_litter_super removes our dentries
return 0;
@@ -266,6 +274,7 @@ static struct file_system_type oprofilefs_type = {
.mount = oprofilefs_mount,
.kill_sb = kill_litter_super,
};
+MODULE_ALIAS_FS("oprofilefs");
int __init oprofilefs_register(void)
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 93404f72dfa..61be1d9c16c 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -74,8 +74,8 @@ static void oprofile_hrtimer_stop(void)
put_online_cpus();
}
-static int __cpuinit oprofile_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static int oprofile_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
{
long cpu = (long) hcpu;