From 403f307576396f3362fbb65af190885b6036c72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Sat, 14 Feb 2009 02:07:24 +0100 Subject: PM: Fix suspend_console and resume_console to use only one semaphore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a race where a thread acquires the console while the console is suspended, and the console is resumed before this thread releases it. In this case, the secondary console semaphore would be left locked, and the primary semaphore would be released twice. This in turn would cause the console switch on suspend or resume to hang forever. Note that suspend_console does not actually lock the console for clients that use acquire_console_sem, it only locks it for clients that use try_acquire_console_sem. If we change suspend_console to fully lock the console, then the kernel may deadlock on suspend. One client of try_acquire_console_sem is acquire_console_semaphore_for_printk, which uses it to prevent printk from using the console while it is suspended. Signed-off-by: Arve Hjønnevåg Signed-off-by: Rafael J. Wysocki Cc: Len Brown Cc: Greg KH Signed-off-by: Linus Torvalds --- kernel/printk.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'kernel/printk.c') diff --git a/kernel/printk.c b/kernel/printk.c index 69188f226a93..e3602d0755b0 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress); * driver system. */ static DECLARE_MUTEX(console_sem); -static DECLARE_MUTEX(secondary_console_sem); struct console *console_drivers; EXPORT_SYMBOL_GPL(console_drivers); @@ -891,12 +890,14 @@ void suspend_console(void) printk("Suspending console(s) (use no_console_suspend to debug)\n"); acquire_console_sem(); console_suspended = 1; + up(&console_sem); } void resume_console(void) { if (!console_suspend_enabled) return; + down(&console_sem); console_suspended = 0; release_console_sem(); } @@ -912,11 +913,9 @@ void resume_console(void) void acquire_console_sem(void) { BUG_ON(in_interrupt()); - if (console_suspended) { - down(&secondary_console_sem); - return; - } down(&console_sem); + if (console_suspended) + return; console_locked = 1; console_may_schedule = 1; } @@ -926,6 +925,10 @@ int try_acquire_console_sem(void) { if (down_trylock(&console_sem)) return -1; + if (console_suspended) { + up(&console_sem); + return -1; + } console_locked = 1; console_may_schedule = 0; return 0; @@ -979,7 +982,7 @@ void release_console_sem(void) unsigned wake_klogd = 0; if (console_suspended) { - up(&secondary_console_sem); + up(&console_sem); return; } -- cgit v1.2.2 From f2d28a2ebcb525a6ec7e2152106ddb385ef52b73 Mon Sep 17 00:00:00 2001 From: Guillaume Knispel Date: Tue, 17 Mar 2009 16:18:42 +0100 Subject: printk: correct the behavior of printk_timed_ratelimit() Impact: fix jiffies-comparison sign-wrap behavior The behavior provided by printk_timed_ratelimit() is, in some situations, probably not what a caller would reasonably expect: bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msecs) { if (*caller_jiffies == 0 || time_after(jiffies, *caller_jiffies)) { *caller_jiffies = jiffies + msecs_to_jiffies(interval_msecs); return true; } return false; } On a 32 bit computer, if printk_timed_ratelimit() is initially called at time jiffies == Ja, *caller_jiffies is set to Ja + msecs_to_jiffies(interval_msecs): let's say Ja + 42 for this example. If this caller then doesn't call printk_timed_ratelimit() until jiffies == Ja + (1 << 31) + 42 (which can happen as soon as ~ 25 days later on a 1000 HZ system), printk_timed_ratelimit() will then always return false to this caller until jiffies loops completely (1 << 31 more ticks). Ths change makes it only return false if jiffies is in the small time window starting at the previous call when true was returned and ending interval_msecs later. Note that if jiffies loops completely between two calls to printk_timed_ratelimit(), it will obviously still wrongly return false, but this is something with a low probability. If something completely reliable is needed I guess jiffies_64 must be used (which this change does not do). Signed-off-by: Guillaume Knispel Cc: Ulrich Drepper Cc: Rusty Russell Cc: Andrew Morton Cc: Linus Torvalds LKML-Reference: <20090317161842.0059096b@xilun.lan.proformatique.com> Signed-off-by: Ingo Molnar --- kernel/printk.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'kernel/printk.c') diff --git a/kernel/printk.c b/kernel/printk.c index e3602d0755b0..2be719908d1f 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1292,8 +1292,11 @@ EXPORT_SYMBOL(printk_ratelimit); bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msecs) { - if (*caller_jiffies == 0 || time_after(jiffies, *caller_jiffies)) { - *caller_jiffies = jiffies + msecs_to_jiffies(interval_msecs); + if (*caller_jiffies == 0 + || !time_in_range(jiffies, *caller_jiffies, + *caller_jiffies + + msecs_to_jiffies(interval_msecs))) { + *caller_jiffies = jiffies; return true; } return false; -- cgit v1.2.2 From 04d491ab2a53008a1aa98ac09561768c7f3adda3 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 2 Apr 2009 16:58:57 -0700 Subject: kexec: add dmesg log symbols to /proc/vmcoreinfo lists It would be nice to be able to extract the dmesg log from a vmcore file without needing to keep the debug symbols for the running kernel handy all the time. We have a facility to do this in /proc/vmcore. This patch adds the log_buf and log_end symbols to the vmcoreinfo area so that tools (like makedumpfile) can easily extract the dmesg logs from a vmcore image. [akpm@linux-foundation.org: several fixes and cleanups] [akpm@linux-foundation.org: fix unused log_buf_kexec_setup()] [akpm@linux-foundation.org: build fix] Signed-off-by: Neil Horman Cc: Simon Horman Acked-by: Vivek Goyal Cc: Neil Horman Cc: Simon Horman Cc: Vivek Goyal Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'kernel/printk.c') diff --git a/kernel/printk.c b/kernel/printk.c index e3602d0755b0..a5f61a9acedb 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -135,6 +136,24 @@ static char *log_buf = __log_buf; static int log_buf_len = __LOG_BUF_LEN; static unsigned logged_chars; /* Number of chars produced since last read+clear operation */ +#ifdef CONFIG_KEXEC +/* + * This appends the listed symbols to /proc/vmcoreinfo + * + * /proc/vmcoreinfo is used by various utiilties, like crash and makedumpfile to + * obtain access to symbols that are otherwise very difficult to locate. These + * symbols are specifically used so that utilities can access and extract the + * dmesg log from a vmcore file after a crash. + */ +void log_buf_kexec_setup(void) +{ + VMCOREINFO_SYMBOL(log_buf); + VMCOREINFO_SYMBOL(log_end); + VMCOREINFO_SYMBOL(log_buf_len); + VMCOREINFO_SYMBOL(logged_chars); +} +#endif + static int __init log_buf_len_setup(char *str) { unsigned size = memparse(str, &str); -- cgit v1.2.2