diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2010-12-03 04:54:16 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-12-06 11:59:31 -0500 |
commit | 0490cd1f9d99569d3bd64e17adc88db06a5007be (patch) | |
tree | a857099ce331773d5103f376860dd3f29f7a8b54 /kernel/kprobes.c | |
parent | 6274de4984a630b45c6934b3ee62e5692c745328 (diff) |
kprobes: Reuse unused kprobe
Reuse unused (waiting for unoptimizing and no user handler)
kprobe on given address instead of returning -EBUSY for
registering a new kprobe.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: 2nddept-manager@sdl.hitachi.co.jp
LKML-Reference: <20101203095416.2961.39080.stgit@ltc236.sdl.hitachi.co.jp>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ba4d4c0740cf..134754d18bb4 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -692,6 +692,27 @@ static __kprobes void unoptimize_kprobe(struct kprobe *p, bool force) | |||
692 | } | 692 | } |
693 | } | 693 | } |
694 | 694 | ||
695 | /* Cancel unoptimizing for reusing */ | ||
696 | static void reuse_unused_kprobe(struct kprobe *ap) | ||
697 | { | ||
698 | struct optimized_kprobe *op; | ||
699 | |||
700 | BUG_ON(!kprobe_unused(ap)); | ||
701 | /* | ||
702 | * Unused kprobe MUST be on the way of delayed unoptimizing (means | ||
703 | * there is still a relative jump) and disabled. | ||
704 | */ | ||
705 | op = container_of(ap, struct optimized_kprobe, kp); | ||
706 | if (unlikely(list_empty(&op->list))) | ||
707 | printk(KERN_WARNING "Warning: found a stray unused " | ||
708 | "aggrprobe@%p\n", ap->addr); | ||
709 | /* Enable the probe again */ | ||
710 | ap->flags &= ~KPROBE_FLAG_DISABLED; | ||
711 | /* Optimize it again (remove from op->list) */ | ||
712 | BUG_ON(!kprobe_optready(ap)); | ||
713 | optimize_kprobe(ap); | ||
714 | } | ||
715 | |||
695 | /* Remove optimized instructions */ | 716 | /* Remove optimized instructions */ |
696 | static void __kprobes kill_optimized_kprobe(struct kprobe *p) | 717 | static void __kprobes kill_optimized_kprobe(struct kprobe *p) |
697 | { | 718 | { |
@@ -872,6 +893,13 @@ static void __kprobes __disarm_kprobe(struct kprobe *p, bool reopt) | |||
872 | #define kprobe_disarmed(p) kprobe_disabled(p) | 893 | #define kprobe_disarmed(p) kprobe_disabled(p) |
873 | #define wait_for_kprobe_optimizer() do {} while (0) | 894 | #define wait_for_kprobe_optimizer() do {} while (0) |
874 | 895 | ||
896 | /* There should be no unused kprobes can be reused without optimization */ | ||
897 | static void reuse_unused_kprobe(struct kprobe *ap) | ||
898 | { | ||
899 | printk(KERN_ERR "Error: There should be no unused kprobe here.\n"); | ||
900 | BUG_ON(kprobe_unused(ap)); | ||
901 | } | ||
902 | |||
875 | static __kprobes void free_aggr_kprobe(struct kprobe *p) | 903 | static __kprobes void free_aggr_kprobe(struct kprobe *p) |
876 | { | 904 | { |
877 | arch_remove_kprobe(p); | 905 | arch_remove_kprobe(p); |
@@ -1173,8 +1201,8 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p, | |||
1173 | return -ENOMEM; | 1201 | return -ENOMEM; |
1174 | init_aggr_kprobe(ap, orig_p); | 1202 | init_aggr_kprobe(ap, orig_p); |
1175 | } else if (kprobe_unused(ap)) | 1203 | } else if (kprobe_unused(ap)) |
1176 | /* Busy to die */ | 1204 | /* This probe is going to die. Rescue it */ |
1177 | return -EBUSY; | 1205 | reuse_unused_kprobe(ap); |
1178 | 1206 | ||
1179 | if (kprobe_gone(ap)) { | 1207 | if (kprobe_gone(ap)) { |
1180 | /* | 1208 | /* |