diff options
author | bibo,mao <bibo.mao@intel.com> | 2006-10-02 05:17:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:16 -0400 |
commit | 99219a3fbc2dcf2eaa954f7b2ac27299fd7894cd (patch) | |
tree | 895abde156c9fbeea9c5a87cfaaa411d4ad175c6 /arch/ia64/kernel/kprobes.c | |
parent | f2aa85a0ccd90110e76c6375535adc3ae358f971 (diff) |
[PATCH] kretprobe spinlock deadlock patch
kprobe_flush_task() possibly calls kfree function during holding
kretprobe_lock spinlock, if kfree function is probed by kretprobe that will
incur spinlock deadlock. This patch moves kfree function out scope of
kretprobe_lock.
Signed-off-by: bibo, mao <bibo.mao@intel.com>
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 9c9c8fcdfbdc..51217d63285e 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -338,12 +338,13 @@ static void kretprobe_trampoline(void) | |||
338 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 338 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
339 | { | 339 | { |
340 | struct kretprobe_instance *ri = NULL; | 340 | struct kretprobe_instance *ri = NULL; |
341 | struct hlist_head *head; | 341 | struct hlist_head *head, empty_rp; |
342 | struct hlist_node *node, *tmp; | 342 | struct hlist_node *node, *tmp; |
343 | unsigned long flags, orig_ret_address = 0; | 343 | unsigned long flags, orig_ret_address = 0; |
344 | unsigned long trampoline_address = | 344 | unsigned long trampoline_address = |
345 | ((struct fnptr *)kretprobe_trampoline)->ip; | 345 | ((struct fnptr *)kretprobe_trampoline)->ip; |
346 | 346 | ||
347 | INIT_HLIST_HEAD(&empty_rp); | ||
347 | spin_lock_irqsave(&kretprobe_lock, flags); | 348 | spin_lock_irqsave(&kretprobe_lock, flags); |
348 | head = kretprobe_inst_table_head(current); | 349 | head = kretprobe_inst_table_head(current); |
349 | 350 | ||
@@ -369,7 +370,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
369 | ri->rp->handler(ri, regs); | 370 | ri->rp->handler(ri, regs); |
370 | 371 | ||
371 | orig_ret_address = (unsigned long)ri->ret_addr; | 372 | orig_ret_address = (unsigned long)ri->ret_addr; |
372 | recycle_rp_inst(ri); | 373 | recycle_rp_inst(ri, &empty_rp); |
373 | 374 | ||
374 | if (orig_ret_address != trampoline_address) | 375 | if (orig_ret_address != trampoline_address) |
375 | /* | 376 | /* |
@@ -387,6 +388,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
387 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 388 | spin_unlock_irqrestore(&kretprobe_lock, flags); |
388 | preempt_enable_no_resched(); | 389 | preempt_enable_no_resched(); |
389 | 390 | ||
391 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | ||
392 | hlist_del(&ri->hlist); | ||
393 | kfree(ri); | ||
394 | } | ||
390 | /* | 395 | /* |
391 | * By returning a non-zero value, we are telling | 396 | * By returning a non-zero value, we are telling |
392 | * kprobe_handler() that we don't want the post_handler | 397 | * kprobe_handler() that we don't want the post_handler |