[PATCH] Kprobe: multi kprobe posthandler for booster
authormao, bibo <bibo.mao@intel.com>
Mon, 26 Jun 2006 07:25:22 +0000 (00:25 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 26 Jun 2006 16:58:22 +0000 (09:58 -0700)
If there are multi kprobes on the same probepoint, there will be one extra
aggr_kprobe on the head of kprobe list.  The aggr_kprobe has
aggr_post_handler/aggr_break_handler whether the other kprobe
post_hander/break_handler is NULL or not.  This patch modifies this, only
when there is one or more kprobe in the list whose post_handler is not
NULL, post_handler of aggr_kprobe will be set as aggr_post_handler.

[soshima@redhat.com: !CONFIG_PREEMPT fix]
Signed-off-by: bibo, mao <bibo.mao@intel.com>
Cc: Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: "Keshavamurthy, Anil S" <anil.s.keshavamurthy@intel.com>
Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Yumiko Sugita <sugita@sdl.hitachi.co.jp>
Cc: Hideo Aoki <haoki@redhat.com>
Signed-off-by: Satoshi Oshima <soshima@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/kprobes.c
kernel/kprobes.c

index 37f86234bdd75c9ca7d21626f3630c71c44a5080..727e419ad78ac496588ea692acad30766bbad37c 100644 (file)
@@ -259,7 +259,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
        struct kprobe_ctlblk *kcb;
 #ifdef CONFIG_PREEMPT
        unsigned pre_preempt_count = preempt_count();
-#endif /* CONFIG_PREEMPT */
+#else
+       unsigned pre_preempt_count = 1;
+#endif
 
        addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
 
@@ -336,22 +338,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
                /* handler has already set things up, so skip ss setup */
                return 1;
 
-       if (p->ainsn.boostable == 1 &&
-#ifdef CONFIG_PREEMPT
-           !(pre_preempt_count) && /*
-                                      * This enables booster when the direct
-                                      * execution path aren't preempted.
-                                      */
-#endif /* CONFIG_PREEMPT */
-           !p->post_handler && !p->break_handler ) {
+ss_probe:
+       if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
                /* Boost up -- we can execute copied instructions directly */
                reset_current_kprobe();
                regs->eip = (unsigned long)p->ainsn.insn;
                preempt_enable_no_resched();
                return 1;
        }
-
-ss_probe:
        prepare_singlestep(p, regs);
        kcb->kprobe_status = KPROBE_HIT_SS;
        return 1;
index 1fbf466a29aab6ca0dfe1cf6e5d6ac16fba546d8..f095178e48c3fdf824dcd2e4af65d8337ef3a1c1 100644 (file)
@@ -368,16 +368,15 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
 */
 static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
 {
-        struct kprobe *kp;
-
        if (p->break_handler) {
-               list_for_each_entry_rcu(kp, &old_p->list, list) {
-                       if (kp->break_handler)
-                               return -EEXIST;
-               }
+               if (old_p->break_handler)
+                       return -EEXIST;
                list_add_tail_rcu(&p->list, &old_p->list);
+               old_p->break_handler = aggr_break_handler;
        } else
                list_add_rcu(&p->list, &old_p->list);
+       if (p->post_handler && !old_p->post_handler)
+               old_p->post_handler = aggr_post_handler;
        return 0;
 }
 
@@ -390,9 +389,11 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
        copy_kprobe(p, ap);
        ap->addr = p->addr;
        ap->pre_handler = aggr_pre_handler;
-       ap->post_handler = aggr_post_handler;
        ap->fault_handler = aggr_fault_handler;
-       ap->break_handler = aggr_break_handler;
+       if (p->post_handler)
+               ap->post_handler = aggr_post_handler;
+       if (p->break_handler)
+               ap->break_handler = aggr_break_handler;
 
        INIT_LIST_HEAD(&ap->list);
        list_add_rcu(&p->list, &ap->list);
@@ -536,6 +537,21 @@ valid_p:
                        kfree(old_p);
                }
                arch_remove_kprobe(p);
+       } else {
+               mutex_lock(&kprobe_mutex);
+               if (p->break_handler)
+                       old_p->break_handler = NULL;
+               if (p->post_handler){
+                       list_for_each_entry_rcu(list_p, &old_p->list, list){
+                               if (list_p->post_handler){
+                                       cleanup_p = 2;
+                                       break;
+                               }
+                       }
+                       if (cleanup_p == 0)
+                               old_p->post_handler = NULL;
+               }
+               mutex_unlock(&kprobe_mutex);
        }
 }