printk: Provide a wake_up_klogd() off-case
wake_up_klogd() is useless when CONFIG_PRINTK=n because neither printk() nor printk_sched() are in use and there are actually no waiter on log_wait waitqueue. It should be a stub in this case for users like bust_spinlocks(). Otherwise this results in this warning when CONFIG_PRINTK=n and CONFIG_IRQ_WORK=n: kernel/built-in.o In function `wake_up_klogd': (.text.wake_up_klogd+0xb4): undefined reference to `irq_work_queue' To fix this, provide an off-case for wake_up_klogd() when CONFIG_PRINTK=n. There is much more from console_unlock() and other console related code in printk.c that should be moved under CONFIG_PRINTK. But for now, focus on a minimal fix as we passed the merged window already. [akpm@linux-foundation.org: include printk.h in bust_spinlocks.c] Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Reported-by: James Hogan <james.hogan@imgtec.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
fe8d52614b
Коммит
dc72c32e1f
|
@ -390,7 +390,6 @@ extern struct pid *session_of_pgrp(struct pid *pgrp);
|
||||||
unsigned long int_sqrt(unsigned long);
|
unsigned long int_sqrt(unsigned long);
|
||||||
|
|
||||||
extern void bust_spinlocks(int yes);
|
extern void bust_spinlocks(int yes);
|
||||||
extern void wake_up_klogd(void);
|
|
||||||
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
|
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
|
||||||
extern int panic_timeout;
|
extern int panic_timeout;
|
||||||
extern int panic_on_oops;
|
extern int panic_on_oops;
|
||||||
|
|
|
@ -134,6 +134,8 @@ extern int printk_delay_msec;
|
||||||
extern int dmesg_restrict;
|
extern int dmesg_restrict;
|
||||||
extern int kptr_restrict;
|
extern int kptr_restrict;
|
||||||
|
|
||||||
|
extern void wake_up_klogd(void);
|
||||||
|
|
||||||
void log_buf_kexec_setup(void);
|
void log_buf_kexec_setup(void);
|
||||||
void __init setup_log_buf(int early);
|
void __init setup_log_buf(int early);
|
||||||
#else
|
#else
|
||||||
|
@ -162,6 +164,10 @@ static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void wake_up_klogd(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void log_buf_kexec_setup(void)
|
static inline void log_buf_kexec_setup(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
|
||||||
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
|
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
|
||||||
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
|
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
|
||||||
|
|
||||||
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
|
||||||
|
|
||||||
int console_printk[4] = {
|
int console_printk[4] = {
|
||||||
DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
|
DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
|
||||||
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
|
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
|
||||||
|
@ -224,6 +222,7 @@ struct log {
|
||||||
static DEFINE_RAW_SPINLOCK(logbuf_lock);
|
static DEFINE_RAW_SPINLOCK(logbuf_lock);
|
||||||
|
|
||||||
#ifdef CONFIG_PRINTK
|
#ifdef CONFIG_PRINTK
|
||||||
|
DECLARE_WAIT_QUEUE_HEAD(log_wait);
|
||||||
/* the next printk record to read by syslog(READ) or /proc/kmsg */
|
/* the next printk record to read by syslog(READ) or /proc/kmsg */
|
||||||
static u64 syslog_seq;
|
static u64 syslog_seq;
|
||||||
static u32 syslog_idx;
|
static u32 syslog_idx;
|
||||||
|
@ -1957,45 +1956,6 @@ int is_console_locked(void)
|
||||||
return console_locked;
|
return console_locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Delayed printk version, for scheduler-internal messages:
|
|
||||||
*/
|
|
||||||
#define PRINTK_BUF_SIZE 512
|
|
||||||
|
|
||||||
#define PRINTK_PENDING_WAKEUP 0x01
|
|
||||||
#define PRINTK_PENDING_SCHED 0x02
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(int, printk_pending);
|
|
||||||
static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
|
|
||||||
|
|
||||||
static void wake_up_klogd_work_func(struct irq_work *irq_work)
|
|
||||||
{
|
|
||||||
int pending = __this_cpu_xchg(printk_pending, 0);
|
|
||||||
|
|
||||||
if (pending & PRINTK_PENDING_SCHED) {
|
|
||||||
char *buf = __get_cpu_var(printk_sched_buf);
|
|
||||||
printk(KERN_WARNING "[sched_delayed] %s", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pending & PRINTK_PENDING_WAKEUP)
|
|
||||||
wake_up_interruptible(&log_wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
|
|
||||||
.func = wake_up_klogd_work_func,
|
|
||||||
.flags = IRQ_WORK_LAZY,
|
|
||||||
};
|
|
||||||
|
|
||||||
void wake_up_klogd(void)
|
|
||||||
{
|
|
||||||
preempt_disable();
|
|
||||||
if (waitqueue_active(&log_wait)) {
|
|
||||||
this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
|
|
||||||
irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
|
|
||||||
}
|
|
||||||
preempt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void console_cont_flush(char *text, size_t size)
|
static void console_cont_flush(char *text, size_t size)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -2458,6 +2418,44 @@ static int __init printk_late_init(void)
|
||||||
late_initcall(printk_late_init);
|
late_initcall(printk_late_init);
|
||||||
|
|
||||||
#if defined CONFIG_PRINTK
|
#if defined CONFIG_PRINTK
|
||||||
|
/*
|
||||||
|
* Delayed printk version, for scheduler-internal messages:
|
||||||
|
*/
|
||||||
|
#define PRINTK_BUF_SIZE 512
|
||||||
|
|
||||||
|
#define PRINTK_PENDING_WAKEUP 0x01
|
||||||
|
#define PRINTK_PENDING_SCHED 0x02
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(int, printk_pending);
|
||||||
|
static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
|
||||||
|
|
||||||
|
static void wake_up_klogd_work_func(struct irq_work *irq_work)
|
||||||
|
{
|
||||||
|
int pending = __this_cpu_xchg(printk_pending, 0);
|
||||||
|
|
||||||
|
if (pending & PRINTK_PENDING_SCHED) {
|
||||||
|
char *buf = __get_cpu_var(printk_sched_buf);
|
||||||
|
printk(KERN_WARNING "[sched_delayed] %s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pending & PRINTK_PENDING_WAKEUP)
|
||||||
|
wake_up_interruptible(&log_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
|
||||||
|
.func = wake_up_klogd_work_func,
|
||||||
|
.flags = IRQ_WORK_LAZY,
|
||||||
|
};
|
||||||
|
|
||||||
|
void wake_up_klogd(void)
|
||||||
|
{
|
||||||
|
preempt_disable();
|
||||||
|
if (waitqueue_active(&log_wait)) {
|
||||||
|
this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
|
||||||
|
irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
|
||||||
|
}
|
||||||
|
preempt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
int printk_sched(const char *fmt, ...)
|
int printk_sched(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
@ -28,5 +29,3 @@ void __attribute__((weak)) bust_spinlocks(int yes)
|
||||||
wake_up_klogd();
|
wake_up_klogd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче