diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-13 13:45:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-13 13:45:49 -0400 |
commit | c78a9b9b8e36b8de302eddbe7a1688af3d9650ff (patch) | |
tree | 3857996cf30ae6a60b5afe2e1e3e30f75fbca05e | |
parent | 842c895d140a75e5d67fa346213deb3ca2b460f8 (diff) | |
parent | 5f127133ee432d0b83ee26e8e3a3d7828ab5f2b1 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
ftrace: Revert 8ab2b7efd ftrace: Remove unnecessary disabling of irqs
kprobes/trace: Fix kprobe selftest for gcc 4.6
ftrace: Fix possible undefined return code
oprofile, dcookies: Fix possible circular locking dependency
oprofile: Fix locking dependency in sync_start()
oprofile: Free potentially owned tasks in case of errors
oprofile, x86: Add comments to IBS LVT offset initialization
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 3 | ||||
-rw-r--r-- | arch/x86/oprofile/op_model_amd.c | 13 | ||||
-rw-r--r-- | drivers/oprofile/buffer_sync.c | 21 | ||||
-rw-r--r-- | fs/dcookies.c | 3 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 9 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 8 |
6 files changed, 39 insertions, 18 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b961af86bfea..b9338b8cf420 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -390,7 +390,8 @@ static unsigned int reserve_eilvt_offset(int offset, unsigned int new) | |||
390 | 390 | ||
391 | /* | 391 | /* |
392 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | 392 | * If mask=1, the LVT entry does not generate interrupts while mask=0 |
393 | * enables the vector. See also the BKDGs. | 393 | * enables the vector. See also the BKDGs. Must be called with |
394 | * preemption disabled. | ||
394 | */ | 395 | */ |
395 | 396 | ||
396 | int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) | 397 | int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) |
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 9fd8a567fe1e..9cbb710dc94b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -609,16 +609,21 @@ static int setup_ibs_ctl(int ibs_eilvt_off) | |||
609 | return 0; | 609 | return 0; |
610 | } | 610 | } |
611 | 611 | ||
612 | /* | ||
613 | * This runs only on the current cpu. We try to find an LVT offset and | ||
614 | * setup the local APIC. For this we must disable preemption. On | ||
615 | * success we initialize all nodes with this offset. This updates then | ||
616 | * the offset in the IBS_CTL per-node msr. The per-core APIC setup of | ||
617 | * the IBS interrupt vector is called from op_amd_setup_ctrs()/op_- | ||
618 | * amd_cpu_shutdown() using the new offset. | ||
619 | */ | ||
612 | static int force_ibs_eilvt_setup(void) | 620 | static int force_ibs_eilvt_setup(void) |
613 | { | 621 | { |
614 | int offset; | 622 | int offset; |
615 | int ret; | 623 | int ret; |
616 | 624 | ||
617 | /* | ||
618 | * find the next free available EILVT entry, skip offset 0, | ||
619 | * pin search to this cpu | ||
620 | */ | ||
621 | preempt_disable(); | 625 | preempt_disable(); |
626 | /* find the next free available EILVT entry, skip offset 0 */ | ||
622 | for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { | 627 | for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { |
623 | if (get_eilvt(offset)) | 628 | if (get_eilvt(offset)) |
624 | break; | 629 | break; |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index a3984f4ef192..f34b5b29fb95 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -141,6 +141,13 @@ static struct notifier_block module_load_nb = { | |||
141 | .notifier_call = module_load_notify, | 141 | .notifier_call = module_load_notify, |
142 | }; | 142 | }; |
143 | 143 | ||
144 | static void free_all_tasks(void) | ||
145 | { | ||
146 | /* make sure we don't leak task structs */ | ||
147 | process_task_mortuary(); | ||
148 | process_task_mortuary(); | ||
149 | } | ||
150 | |||
144 | int sync_start(void) | 151 | int sync_start(void) |
145 | { | 152 | { |
146 | int err; | 153 | int err; |
@@ -148,8 +155,6 @@ int sync_start(void) | |||
148 | if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) | 155 | if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) |
149 | return -ENOMEM; | 156 | return -ENOMEM; |
150 | 157 | ||
151 | mutex_lock(&buffer_mutex); | ||
152 | |||
153 | err = task_handoff_register(&task_free_nb); | 158 | err = task_handoff_register(&task_free_nb); |
154 | if (err) | 159 | if (err) |
155 | goto out1; | 160 | goto out1; |
@@ -166,7 +171,6 @@ int sync_start(void) | |||
166 | start_cpu_work(); | 171 | start_cpu_work(); |
167 | 172 | ||
168 | out: | 173 | out: |
169 | mutex_unlock(&buffer_mutex); | ||
170 | return err; | 174 | return err; |
171 | out4: | 175 | out4: |
172 | profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); | 176 | profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); |
@@ -174,6 +178,7 @@ out3: | |||
174 | profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); | 178 | profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); |
175 | out2: | 179 | out2: |
176 | task_handoff_unregister(&task_free_nb); | 180 | task_handoff_unregister(&task_free_nb); |
181 | free_all_tasks(); | ||
177 | out1: | 182 | out1: |
178 | free_cpumask_var(marked_cpus); | 183 | free_cpumask_var(marked_cpus); |
179 | goto out; | 184 | goto out; |
@@ -182,20 +187,16 @@ out1: | |||
182 | 187 | ||
183 | void sync_stop(void) | 188 | void sync_stop(void) |
184 | { | 189 | { |
185 | /* flush buffers */ | ||
186 | mutex_lock(&buffer_mutex); | ||
187 | end_cpu_work(); | 190 | end_cpu_work(); |
188 | unregister_module_notifier(&module_load_nb); | 191 | unregister_module_notifier(&module_load_nb); |
189 | profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); | 192 | profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); |
190 | profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); | 193 | profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); |
191 | task_handoff_unregister(&task_free_nb); | 194 | task_handoff_unregister(&task_free_nb); |
192 | mutex_unlock(&buffer_mutex); | 195 | barrier(); /* do all of the above first */ |
193 | flush_cpu_work(); | ||
194 | 196 | ||
195 | /* make sure we don't leak task structs */ | 197 | flush_cpu_work(); |
196 | process_task_mortuary(); | ||
197 | process_task_mortuary(); | ||
198 | 198 | ||
199 | free_all_tasks(); | ||
199 | free_cpumask_var(marked_cpus); | 200 | free_cpumask_var(marked_cpus); |
200 | } | 201 | } |
201 | 202 | ||
diff --git a/fs/dcookies.c b/fs/dcookies.c index a21cabdbd87b..dda0dc702d1b 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
@@ -178,6 +178,8 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) | |||
178 | /* FIXME: (deleted) ? */ | 178 | /* FIXME: (deleted) ? */ |
179 | path = d_path(&dcs->path, kbuf, PAGE_SIZE); | 179 | path = d_path(&dcs->path, kbuf, PAGE_SIZE); |
180 | 180 | ||
181 | mutex_unlock(&dcookie_mutex); | ||
182 | |||
181 | if (IS_ERR(path)) { | 183 | if (IS_ERR(path)) { |
182 | err = PTR_ERR(path); | 184 | err = PTR_ERR(path); |
183 | goto out_free; | 185 | goto out_free; |
@@ -194,6 +196,7 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len) | |||
194 | 196 | ||
195 | out_free: | 197 | out_free: |
196 | kfree(kbuf); | 198 | kfree(kbuf); |
199 | return err; | ||
197 | out: | 200 | out: |
198 | mutex_unlock(&dcookie_mutex); | 201 | mutex_unlock(&dcookie_mutex); |
199 | return err; | 202 | return err; |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1ee417fcbfa5..908038f57440 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -2740,7 +2740,7 @@ static int ftrace_process_regex(struct ftrace_hash *hash, | |||
2740 | { | 2740 | { |
2741 | char *func, *command, *next = buff; | 2741 | char *func, *command, *next = buff; |
2742 | struct ftrace_func_command *p; | 2742 | struct ftrace_func_command *p; |
2743 | int ret; | 2743 | int ret = -EINVAL; |
2744 | 2744 | ||
2745 | func = strsep(&next, ":"); | 2745 | func = strsep(&next, ":"); |
2746 | 2746 | ||
@@ -3330,6 +3330,7 @@ static int ftrace_process_locs(struct module *mod, | |||
3330 | { | 3330 | { |
3331 | unsigned long *p; | 3331 | unsigned long *p; |
3332 | unsigned long addr; | 3332 | unsigned long addr; |
3333 | unsigned long flags; | ||
3333 | 3334 | ||
3334 | mutex_lock(&ftrace_lock); | 3335 | mutex_lock(&ftrace_lock); |
3335 | p = start; | 3336 | p = start; |
@@ -3346,7 +3347,13 @@ static int ftrace_process_locs(struct module *mod, | |||
3346 | ftrace_record_ip(addr); | 3347 | ftrace_record_ip(addr); |
3347 | } | 3348 | } |
3348 | 3349 | ||
3350 | /* | ||
3351 | * Disable interrupts to prevent interrupts from executing | ||
3352 | * code that is being modified. | ||
3353 | */ | ||
3354 | local_irq_save(flags); | ||
3349 | ftrace_update_code(mod); | 3355 | ftrace_update_code(mod); |
3356 | local_irq_restore(flags); | ||
3350 | mutex_unlock(&ftrace_lock); | 3357 | mutex_unlock(&ftrace_lock); |
3351 | 3358 | ||
3352 | return 0; | 3359 | return 0; |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index f925c45f0afa..27d13b36b8be 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -1870,8 +1870,12 @@ fs_initcall(init_kprobe_trace); | |||
1870 | 1870 | ||
1871 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 1871 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
1872 | 1872 | ||
1873 | static int kprobe_trace_selftest_target(int a1, int a2, int a3, | 1873 | /* |
1874 | int a4, int a5, int a6) | 1874 | * The "__used" keeps gcc from removing the function symbol |
1875 | * from the kallsyms table. | ||
1876 | */ | ||
1877 | static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, | ||
1878 | int a4, int a5, int a6) | ||
1875 | { | 1879 | { |
1876 | return a1 + a2 + a3 + a4 + a5 + a6; | 1880 | return a1 + a2 + a3 + a4 + a5 + a6; |
1877 | } | 1881 | } |