diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2009-03-06 10:36:38 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-06 10:49:00 -0500 |
commit | 4460fdad85becd569f11501ad5b91814814335ff (patch) | |
tree | 7c781d0131f6130498ee2a346c7e95eb9b9b869f /kernel/kprobes.c | |
parent | 0e39ac444636ff5be39b26f1cb56d79594654dda (diff) |
tracing, Text Edit Lock - kprobes architecture independent support
Use the mutual exclusion provided by the text edit lock in the kprobes code. It
allows coherent manipulation of the kernel code by other subsystems.
Changelog:
Move the kernel_text_lock/unlock out of the for loops.
Use text_mutex directly instead of a function.
Remove whitespace modifications.
(note : kprobes_mutex is always taken outside of text_mutex)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@redhat.com>
LKML-Reference: <49B14306.2080202@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 7ba8cd9845cb..479d4d5672f9 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/debugfs.h> | 44 | #include <linux/debugfs.h> |
45 | #include <linux/kdebug.h> | 45 | #include <linux/kdebug.h> |
46 | #include <linux/memory.h> | ||
46 | 47 | ||
47 | #include <asm-generic/sections.h> | 48 | #include <asm-generic/sections.h> |
48 | #include <asm/cacheflush.h> | 49 | #include <asm/cacheflush.h> |
@@ -699,9 +700,10 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
699 | goto out; | 700 | goto out; |
700 | } | 701 | } |
701 | 702 | ||
703 | mutex_lock(&text_mutex); | ||
702 | ret = arch_prepare_kprobe(p); | 704 | ret = arch_prepare_kprobe(p); |
703 | if (ret) | 705 | if (ret) |
704 | goto out; | 706 | goto out_unlock_text; |
705 | 707 | ||
706 | INIT_HLIST_NODE(&p->hlist); | 708 | INIT_HLIST_NODE(&p->hlist); |
707 | hlist_add_head_rcu(&p->hlist, | 709 | hlist_add_head_rcu(&p->hlist, |
@@ -710,6 +712,8 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
710 | if (kprobe_enabled) | 712 | if (kprobe_enabled) |
711 | arch_arm_kprobe(p); | 713 | arch_arm_kprobe(p); |
712 | 714 | ||
715 | out_unlock_text: | ||
716 | mutex_unlock(&text_mutex); | ||
713 | out: | 717 | out: |
714 | mutex_unlock(&kprobe_mutex); | 718 | mutex_unlock(&kprobe_mutex); |
715 | 719 | ||
@@ -746,8 +750,11 @@ valid_p: | |||
746 | * enabled and not gone - otherwise, the breakpoint would | 750 | * enabled and not gone - otherwise, the breakpoint would |
747 | * already have been removed. We save on flushing icache. | 751 | * already have been removed. We save on flushing icache. |
748 | */ | 752 | */ |
749 | if (kprobe_enabled && !kprobe_gone(old_p)) | 753 | if (kprobe_enabled && !kprobe_gone(old_p)) { |
754 | mutex_lock(&text_mutex); | ||
750 | arch_disarm_kprobe(p); | 755 | arch_disarm_kprobe(p); |
756 | mutex_unlock(&text_mutex); | ||
757 | } | ||
751 | hlist_del_rcu(&old_p->hlist); | 758 | hlist_del_rcu(&old_p->hlist); |
752 | } else { | 759 | } else { |
753 | if (p->break_handler && !kprobe_gone(p)) | 760 | if (p->break_handler && !kprobe_gone(p)) |
@@ -1280,12 +1287,14 @@ static void __kprobes enable_all_kprobes(void) | |||
1280 | if (kprobe_enabled) | 1287 | if (kprobe_enabled) |
1281 | goto already_enabled; | 1288 | goto already_enabled; |
1282 | 1289 | ||
1290 | mutex_lock(&text_mutex); | ||
1283 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1291 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
1284 | head = &kprobe_table[i]; | 1292 | head = &kprobe_table[i]; |
1285 | hlist_for_each_entry_rcu(p, node, head, hlist) | 1293 | hlist_for_each_entry_rcu(p, node, head, hlist) |
1286 | if (!kprobe_gone(p)) | 1294 | if (!kprobe_gone(p)) |
1287 | arch_arm_kprobe(p); | 1295 | arch_arm_kprobe(p); |
1288 | } | 1296 | } |
1297 | mutex_unlock(&text_mutex); | ||
1289 | 1298 | ||
1290 | kprobe_enabled = true; | 1299 | kprobe_enabled = true; |
1291 | printk(KERN_INFO "Kprobes globally enabled\n"); | 1300 | printk(KERN_INFO "Kprobes globally enabled\n"); |
@@ -1310,6 +1319,7 @@ static void __kprobes disable_all_kprobes(void) | |||
1310 | 1319 | ||
1311 | kprobe_enabled = false; | 1320 | kprobe_enabled = false; |
1312 | printk(KERN_INFO "Kprobes globally disabled\n"); | 1321 | printk(KERN_INFO "Kprobes globally disabled\n"); |
1322 | mutex_lock(&text_mutex); | ||
1313 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1323 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
1314 | head = &kprobe_table[i]; | 1324 | head = &kprobe_table[i]; |
1315 | hlist_for_each_entry_rcu(p, node, head, hlist) { | 1325 | hlist_for_each_entry_rcu(p, node, head, hlist) { |
@@ -1318,6 +1328,7 @@ static void __kprobes disable_all_kprobes(void) | |||
1318 | } | 1328 | } |
1319 | } | 1329 | } |
1320 | 1330 | ||
1331 | mutex_unlock(&text_mutex); | ||
1321 | mutex_unlock(&kprobe_mutex); | 1332 | mutex_unlock(&kprobe_mutex); |
1322 | /* Allow all currently running kprobes to complete */ | 1333 | /* Allow all currently running kprobes to complete */ |
1323 | synchronize_sched(); | 1334 | synchronize_sched(); |