aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorbibo,mao <bibo.mao@intel.com>2006-10-02 05:17:35 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:16 -0400
commit99219a3fbc2dcf2eaa954f7b2ac27299fd7894cd (patch)
tree895abde156c9fbeea9c5a87cfaaa411d4ad175c6 /arch/s390
parentf2aa85a0ccd90110e76c6375535adc3ae358f971 (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/s390')
-rw-r--r--arch/s390/kernel/kprobes.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index ca28fb0b3790..4d9ff5ce4cbd 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -369,11 +369,12 @@ void __kprobes kretprobe_trampoline_holder(void)
369int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) 369int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
370{ 370{
371 struct kretprobe_instance *ri = NULL; 371 struct kretprobe_instance *ri = NULL;
372 struct hlist_head *head; 372 struct hlist_head *head, empty_rp;
373 struct hlist_node *node, *tmp; 373 struct hlist_node *node, *tmp;
374 unsigned long flags, orig_ret_address = 0; 374 unsigned long flags, orig_ret_address = 0;
375 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; 375 unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
376 376
377 INIT_HLIST_HEAD(&empty_rp);
377 spin_lock_irqsave(&kretprobe_lock, flags); 378 spin_lock_irqsave(&kretprobe_lock, flags);
378 head = kretprobe_inst_table_head(current); 379 head = kretprobe_inst_table_head(current);
379 380
@@ -399,7 +400,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
399 ri->rp->handler(ri, regs); 400 ri->rp->handler(ri, regs);
400 401
401 orig_ret_address = (unsigned long)ri->ret_addr; 402 orig_ret_address = (unsigned long)ri->ret_addr;
402 recycle_rp_inst(ri); 403 recycle_rp_inst(ri, &empty_rp);
403 404
404 if (orig_ret_address != trampoline_address) { 405 if (orig_ret_address != trampoline_address) {
405 /* 406 /*
@@ -417,6 +418,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
417 spin_unlock_irqrestore(&kretprobe_lock, flags); 418 spin_unlock_irqrestore(&kretprobe_lock, flags);
418 preempt_enable_no_resched(); 419 preempt_enable_no_resched();
419 420
421 hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
422 hlist_del(&ri->hlist);
423 kfree(ri);
424 }
420 /* 425 /*
421 * By returning a non-zero value, we are telling 426 * By returning a non-zero value, we are telling
422 * kprobe_handler() that we don't want the post_handler 427 * kprobe_handler() that we don't want the post_handler