aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeshavamurthy Anil S <anil.s.keshavamurthy@intel.com>2006-01-09 23:52:44 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:40 -0500
commitf709b122343fb9a010b6cf2d5559641f1820f7c9 (patch)
tree5019515d4debd995570ffd35b6311fdd26456306
parent49a2a1b83ba6fa40c41968d6a28ba16e7ed0c3f7 (diff)
[PATCH] kprobes-changed-from-using-spinlock-to-mutex fix
Based on some feedback from Oleg Nesterov, I have made few changes to previously posted patch. Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/powerpc/kernel/kprobes.c3
-rw-r--r--arch/x86_64/kernel/kprobes.c4
-rw-r--r--kernel/kprobes.c32
3 files changed, 20 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 331e169e8629..2cd32dd6898b 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -35,7 +35,6 @@
35#include <asm/kdebug.h> 35#include <asm/kdebug.h>
36#include <asm/sstep.h> 36#include <asm/sstep.h>
37 37
38static DECLARE_MUTEX(kprobe_mutex);
39DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 38DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
40DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 39DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
41 40
@@ -54,9 +53,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
54 53
55 /* insn must be on a special executable page on ppc64 */ 54 /* insn must be on a special executable page on ppc64 */
56 if (!ret) { 55 if (!ret) {
57 down(&kprobe_mutex);
58 p->ainsn.insn = get_insn_slot(); 56 p->ainsn.insn = get_insn_slot();
59 up(&kprobe_mutex);
60 if (!p->ainsn.insn) 57 if (!p->ainsn.insn)
61 ret = -ENOMEM; 58 ret = -ENOMEM;
62 } 59 }
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 8b8943bfb89e..128e18190f99 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -43,7 +43,7 @@
43#include <asm/kdebug.h> 43#include <asm/kdebug.h>
44 44
45void jprobe_return_end(void); 45void jprobe_return_end(void);
46void __kprobes arch_copy_kprobe(struct kprobe *p); 46static void __kprobes arch_copy_kprobe(struct kprobe *p);
47 47
48DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 48DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
49DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 49DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -180,7 +180,7 @@ static inline s32 *is_riprel(u8 *insn)
180 return NULL; 180 return NULL;
181} 181}
182 182
183void __kprobes arch_copy_kprobe(struct kprobe *p) 183static void __kprobes arch_copy_kprobe(struct kprobe *p)
184{ 184{
185 s32 *ripdisp; 185 s32 *ripdisp;
186 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE); 186 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index f14ccd35e9b6..f1c0e61a2cb4 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -431,7 +431,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
431 copy_kprobe(old_p, p); 431 copy_kprobe(old_p, p);
432 ret = add_new_kprobe(old_p, p); 432 ret = add_new_kprobe(old_p, p);
433 } else { 433 } else {
434 ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC); 434 ap = kcalloc(1, sizeof(struct kprobe), GFP_KERNEL);
435 if (!ap) 435 if (!ap)
436 return -ENOMEM; 436 return -ENOMEM;
437 add_aggr_kprobe(ap, old_p); 437 add_aggr_kprobe(ap, old_p);
@@ -491,7 +491,8 @@ out:
491void __kprobes unregister_kprobe(struct kprobe *p) 491void __kprobes unregister_kprobe(struct kprobe *p)
492{ 492{
493 struct module *mod; 493 struct module *mod;
494 struct kprobe *old_p, *cleanup_p; 494 struct kprobe *old_p, *list_p;
495 int cleanup_p;
495 496
496 down(&kprobe_mutex); 497 down(&kprobe_mutex);
497 old_p = get_kprobe(p->addr); 498 old_p = get_kprobe(p->addr);
@@ -499,22 +500,25 @@ void __kprobes unregister_kprobe(struct kprobe *p)
499 up(&kprobe_mutex); 500 up(&kprobe_mutex);
500 return; 501 return;
501 } 502 }
502 503 if (p != old_p) {
503 if ((old_p->pre_handler == aggr_pre_handler) && 504 list_for_each_entry_rcu(list_p, &old_p->list, list)
505 if (list_p == p)
506 /* kprobe p is a valid probe */
507 goto valid_p;
508 up(&kprobe_mutex);
509 return;
510 }
511valid_p:
512 if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
504 (p->list.next == &old_p->list) && 513 (p->list.next == &old_p->list) &&
505 (p->list.prev == &old_p->list)) { 514 (p->list.prev == &old_p->list))) {
506 /* Only one element in the aggregate list */ 515 /* Only probe on the hash list */
507 arch_disarm_kprobe(p); 516 arch_disarm_kprobe(p);
508 hlist_del_rcu(&old_p->hlist); 517 hlist_del_rcu(&old_p->hlist);
509 cleanup_p = old_p; 518 cleanup_p = 1;
510 } else if (old_p == p) {
511 /* Only one kprobe element in the hash list */
512 arch_disarm_kprobe(p);
513 hlist_del_rcu(&p->hlist);
514 cleanup_p = p;
515 } else { 519 } else {
516 list_del_rcu(&p->list); 520 list_del_rcu(&p->list);
517 cleanup_p = NULL; 521 cleanup_p = 0;
518 } 522 }
519 523
520 up(&kprobe_mutex); 524 up(&kprobe_mutex);
@@ -524,7 +528,7 @@ void __kprobes unregister_kprobe(struct kprobe *p)
524 module_put(mod); 528 module_put(mod);
525 529
526 if (cleanup_p) { 530 if (cleanup_p) {
527 if (cleanup_p->pre_handler == aggr_pre_handler) { 531 if (p != old_p) {
528 list_del_rcu(&p->list); 532 list_del_rcu(&p->list);
529 kfree(old_p); 533 kfree(old_p);
530 } 534 }