Commit 38335cc5 authored by Petr Mladek's avatar Petr Mladek

Merge branch 'rework/kthreads' into for-linus

parents 12831f64 b87f0230
...@@ -173,6 +173,7 @@ extern void printk_prefer_direct_enter(void); ...@@ -173,6 +173,7 @@ extern void printk_prefer_direct_enter(void);
extern void printk_prefer_direct_exit(void); extern void printk_prefer_direct_exit(void);
extern bool pr_flush(int timeout_ms, bool reset_on_progress); extern bool pr_flush(int timeout_ms, bool reset_on_progress);
extern void try_block_console_kthreads(int timeout_ms);
/* /*
* Please don't use printk_ratelimit(), because it shares ratelimiting state * Please don't use printk_ratelimit(), because it shares ratelimiting state
...@@ -237,6 +238,10 @@ static inline bool pr_flush(int timeout_ms, bool reset_on_progress) ...@@ -237,6 +238,10 @@ static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
return true; return true;
} }
static inline void try_block_console_kthreads(int timeout_ms)
{
}
static inline int printk_ratelimit(void) static inline int printk_ratelimit(void)
{ {
return 0; return 0;
......
...@@ -297,6 +297,7 @@ void panic(const char *fmt, ...) ...@@ -297,6 +297,7 @@ void panic(const char *fmt, ...)
* unfortunately means it may not be hardened to work in a * unfortunately means it may not be hardened to work in a
* panic situation. * panic situation.
*/ */
try_block_console_kthreads(10000);
smp_send_stop(); smp_send_stop();
} else { } else {
/* /*
...@@ -304,6 +305,7 @@ void panic(const char *fmt, ...) ...@@ -304,6 +305,7 @@ void panic(const char *fmt, ...)
* kmsg_dump, we will need architecture dependent extra * kmsg_dump, we will need architecture dependent extra
* works in addition to stopping other CPUs. * works in addition to stopping other CPUs.
*/ */
try_block_console_kthreads(10000);
crash_smp_send_stop(); crash_smp_send_stop();
} }
......
...@@ -20,6 +20,8 @@ enum printk_info_flags { ...@@ -20,6 +20,8 @@ enum printk_info_flags {
LOG_CONT = 8, /* text is a fragment of a continuation line */ LOG_CONT = 8, /* text is a fragment of a continuation line */
}; };
extern bool block_console_kthreads;
__printf(4, 0) __printf(4, 0)
int vprintk_store(int facility, int level, int vprintk_store(int facility, int level,
const struct dev_printk_info *dev_info, const struct dev_printk_info *dev_info,
......
...@@ -250,6 +250,9 @@ static atomic_t console_kthreads_active = ATOMIC_INIT(0); ...@@ -250,6 +250,9 @@ static atomic_t console_kthreads_active = ATOMIC_INIT(0);
#define console_kthread_printing_exit() \ #define console_kthread_printing_exit() \
atomic_dec(&console_kthreads_active) atomic_dec(&console_kthreads_active)
/* Block console kthreads to avoid processing new messages. */
bool block_console_kthreads;
/* /*
* Helper macros to handle lockdep when locking/unlocking console_sem. We use * Helper macros to handle lockdep when locking/unlocking console_sem. We use
* macros instead of functions so that _RET_IP_ contains useful information. * macros instead of functions so that _RET_IP_ contains useful information.
...@@ -3729,7 +3732,10 @@ static bool printer_should_wake(struct console *con, u64 seq) ...@@ -3729,7 +3732,10 @@ static bool printer_should_wake(struct console *con, u64 seq)
return true; return true;
if (con->blocked || if (con->blocked ||
console_kthreads_atomically_blocked()) { console_kthreads_atomically_blocked() ||
block_console_kthreads ||
system_state > SYSTEM_RUNNING ||
oops_in_progress) {
return false; return false;
} }
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/console.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/delay.h>
#include "internal.h" #include "internal.h"
...@@ -50,3 +52,33 @@ asmlinkage int vprintk(const char *fmt, va_list args) ...@@ -50,3 +52,33 @@ asmlinkage int vprintk(const char *fmt, va_list args)
return vprintk_default(fmt, args); return vprintk_default(fmt, args);
} }
EXPORT_SYMBOL(vprintk); EXPORT_SYMBOL(vprintk);
/**
* try_block_console_kthreads() - Try to block console kthreads and
* make the global console_lock() avaialble
*
* @timeout_ms: The maximum time (in ms) to wait.
*
* Prevent console kthreads from starting processing new messages. Wait
* until the global console_lock() become available.
*
* Context: Can be called in any context.
*/
void try_block_console_kthreads(int timeout_ms)
{
block_console_kthreads = true;
/* Do not wait when the console lock could not be safely taken. */
if (this_cpu_read(printk_context) || in_nmi())
return;
while (timeout_ms > 0) {
if (console_trylock()) {
console_unlock();
return;
}
udelay(1000);
timeout_ms -= 1;
}
}
...@@ -82,6 +82,7 @@ void kernel_restart_prepare(char *cmd) ...@@ -82,6 +82,7 @@ void kernel_restart_prepare(char *cmd)
{ {
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART; system_state = SYSTEM_RESTART;
try_block_console_kthreads(10000);
usermodehelper_disable(); usermodehelper_disable();
device_shutdown(); device_shutdown();
} }
...@@ -270,6 +271,7 @@ static void kernel_shutdown_prepare(enum system_states state) ...@@ -270,6 +271,7 @@ static void kernel_shutdown_prepare(enum system_states state)
blocking_notifier_call_chain(&reboot_notifier_list, blocking_notifier_call_chain(&reboot_notifier_list,
(state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL); (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
system_state = state; system_state = state;
try_block_console_kthreads(10000);
usermodehelper_disable(); usermodehelper_disable();
device_shutdown(); device_shutdown();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment