From b58d977432c80ee60d6970042775a62e3f8d7675 Mon Sep 17 00:00:00 2001 From: Alex Thorlton Date: Wed, 3 Jul 2013 15:04:59 -0700 Subject: dump_stack: serialize the output from dump_stack() Add functionality to serialize the output from dump_stack() to avoid mangling of the output when dump_stack is called simultaneously from multiple cpus. [akpm@linux-foundation.org: fix comment indenting, avoid inclusion of files - use where possiblem fix uniprocessor build (__dump_stack undefined), remove unneeded ifdef around smp.h inclusion] Signed-off-by: Alex Thorlton Reported-by: Russ Anderson Reviewed-by: Robin Holt Cc: Vineet Gupta Cc: David S. Miller Cc: Richard Kuo Cc: Jesper Nilsson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/dump_stack.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/dump_stack.c b/lib/dump_stack.c index 53bad099ebd6..c03154173cc7 100644 --- a/lib/dump_stack.c +++ b/lib/dump_stack.c @@ -6,15 +6,58 @@ #include #include #include +#include +#include + +static void __dump_stack(void) +{ + dump_stack_print_info(KERN_DEFAULT); + show_stack(NULL, NULL); +} /** * dump_stack - dump the current task information and its stack trace * * Architectures can override this implementation by implementing its own. */ +#ifdef CONFIG_SMP +static atomic_t dump_lock = ATOMIC_INIT(-1); + void dump_stack(void) { - dump_stack_print_info(KERN_DEFAULT); - show_stack(NULL, NULL); + int was_locked; + int old; + int cpu; + + /* + * Permit this cpu to perform nested stack dumps while serialising + * against other CPUs + */ + preempt_disable(); + +retry: + cpu = smp_processor_id(); + old = atomic_cmpxchg(&dump_lock, -1, cpu); + if (old == -1) { + was_locked = 0; + } else if (old == cpu) { + was_locked = 1; + } else { + cpu_relax(); + goto retry; + } + + __dump_stack(); + + if (!was_locked) + atomic_set(&dump_lock, -1); + + preempt_enable(); +} +#else +void dump_stack(void) +{ + __dump_stack(); } +#endif EXPORT_SYMBOL(dump_stack); -- cgit v1.2.3 From 64df3071a97f20767f63b88c573791691a855b5c Mon Sep 17 00:00:00 2001 From: Fan Du Date: Wed, 3 Jul 2013 15:05:19 -0700 Subject: lib/percpu_counter.c: __this_cpu_write() doesn't need to be protected by spinlock __this_cpu_write doesn't need to be protected by spinlock, AS we are doing per cpu write with preempt disabled. And another reason to remove __this_cpu_write outside of spinlock: __percpu_counter_sum is not an accurate counter. Signed-off-by: Fan Du Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/percpu_counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index ba6085d9c741..1fc23a3277e1 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -80,8 +80,8 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) if (count >= batch || count <= -batch) { raw_spin_lock(&fbc->lock); fbc->count += count; - __this_cpu_write(*fbc->counters, 0); raw_spin_unlock(&fbc->lock); + __this_cpu_write(*fbc->counters, 0); } else { __this_cpu_write(*fbc->counters, count); } -- cgit v1.2.3 From dd04b452f532ca100f7c557295ffcbc049c77171 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 3 Jul 2013 15:08:47 -0700 Subject: idr: print a stack dump after ida_remove warning We print a dump stack after idr_remove warning. This is useful to find the faulty piece of code. Let's do the same for ida_remove, as it would be equally useful there. [akpm@linux-foundation.org: convert the open-coded printk+dump_stack into WARN()] Signed-off-by: Jean Delvare Cc: Tejun Heo Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/idr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/idr.c b/lib/idr.c index cca4b9302a71..bfe4db4e165f 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -524,9 +524,7 @@ EXPORT_SYMBOL(idr_alloc_cyclic); static void idr_remove_warning(int id) { - printk(KERN_WARNING - "idr_remove called for id=%d which is not allocated.\n", id); - dump_stack(); + WARN(1, "idr_remove called for id=%d which is not allocated.\n", id); } static void sub_remove(struct idr *idp, int shift, int id) @@ -1064,8 +1062,7 @@ void ida_remove(struct ida *ida, int id) return; err: - printk(KERN_WARNING - "ida_remove called for id=%d which is not allocated.\n", id); + WARN(1, "ida_remove called for id=%d which is not allocated.\n", id); } EXPORT_SYMBOL(ida_remove); -- cgit v1.2.3