Skip to content

Commit 38335cc

Browse files
committed
Merge branch 'rework/kthreads' into for-linus
2 parents 12831f6 + b87f023 commit 38335cc

File tree

6 files changed

+50
-1
lines changed

6 files changed

+50
-1
lines changed

include/linux/printk.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ extern void printk_prefer_direct_enter(void);
173173
extern void printk_prefer_direct_exit(void);
174174

175175
extern bool pr_flush(int timeout_ms, bool reset_on_progress);
176+
extern void try_block_console_kthreads(int timeout_ms);
176177

177178
/*
178179
* 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)
237238
return true;
238239
}
239240

241+
static inline void try_block_console_kthreads(int timeout_ms)
242+
{
243+
}
244+
240245
static inline int printk_ratelimit(void)
241246
{
242247
return 0;

kernel/panic.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,15 @@ void panic(const char *fmt, ...)
297297
* unfortunately means it may not be hardened to work in a
298298
* panic situation.
299299
*/
300+
try_block_console_kthreads(10000);
300301
smp_send_stop();
301302
} else {
302303
/*
303304
* If we want to do crash dump after notifier calls and
304305
* kmsg_dump, we will need architecture dependent extra
305306
* works in addition to stopping other CPUs.
306307
*/
308+
try_block_console_kthreads(10000);
307309
crash_smp_send_stop();
308310
}
309311

kernel/printk/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum printk_info_flags {
2020
LOG_CONT = 8, /* text is a fragment of a continuation line */
2121
};
2222

23+
extern bool block_console_kthreads;
24+
2325
__printf(4, 0)
2426
int vprintk_store(int facility, int level,
2527
const struct dev_printk_info *dev_info,

kernel/printk/printk.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ static atomic_t console_kthreads_active = ATOMIC_INIT(0);
250250
#define console_kthread_printing_exit() \
251251
atomic_dec(&console_kthreads_active)
252252

253+
/* Block console kthreads to avoid processing new messages. */
254+
bool block_console_kthreads;
255+
253256
/*
254257
* Helper macros to handle lockdep when locking/unlocking console_sem. We use
255258
* 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)
37293732
return true;
37303733

37313734
if (con->blocked ||
3732-
console_kthreads_atomically_blocked()) {
3735+
console_kthreads_atomically_blocked() ||
3736+
block_console_kthreads ||
3737+
system_state > SYSTEM_RUNNING ||
3738+
oops_in_progress) {
37333739
return false;
37343740
}
37353741

kernel/printk/printk_safe.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
#include <linux/smp.h>
99
#include <linux/cpumask.h>
1010
#include <linux/printk.h>
11+
#include <linux/console.h>
1112
#include <linux/kprobes.h>
13+
#include <linux/delay.h>
1214

1315
#include "internal.h"
1416

@@ -50,3 +52,33 @@ asmlinkage int vprintk(const char *fmt, va_list args)
5052
return vprintk_default(fmt, args);
5153
}
5254
EXPORT_SYMBOL(vprintk);
55+
56+
/**
57+
* try_block_console_kthreads() - Try to block console kthreads and
58+
* make the global console_lock() avaialble
59+
*
60+
* @timeout_ms: The maximum time (in ms) to wait.
61+
*
62+
* Prevent console kthreads from starting processing new messages. Wait
63+
* until the global console_lock() become available.
64+
*
65+
* Context: Can be called in any context.
66+
*/
67+
void try_block_console_kthreads(int timeout_ms)
68+
{
69+
block_console_kthreads = true;
70+
71+
/* Do not wait when the console lock could not be safely taken. */
72+
if (this_cpu_read(printk_context) || in_nmi())
73+
return;
74+
75+
while (timeout_ms > 0) {
76+
if (console_trylock()) {
77+
console_unlock();
78+
return;
79+
}
80+
81+
udelay(1000);
82+
timeout_ms -= 1;
83+
}
84+
}

kernel/reboot.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ void kernel_restart_prepare(char *cmd)
8282
{
8383
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
8484
system_state = SYSTEM_RESTART;
85+
try_block_console_kthreads(10000);
8586
usermodehelper_disable();
8687
device_shutdown();
8788
}
@@ -270,6 +271,7 @@ static void kernel_shutdown_prepare(enum system_states state)
270271
blocking_notifier_call_chain(&reboot_notifier_list,
271272
(state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
272273
system_state = state;
274+
try_block_console_kthreads(10000);
273275
usermodehelper_disable();
274276
device_shutdown();
275277
}

0 commit comments

Comments
 (0)