Commit 34767e53 authored by Petr Mladek's avatar Petr Mladek
Browse files

Merge branch 'for-6.13-force-console' into for-linus

parents a961ec4e da115c4e
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -582,7 +582,6 @@ static void __sysrq_put_key_op(u8 key, const struct sysrq_key_op *op_p)
void __handle_sysrq(u8 key, bool check_mask)
{
	const struct sysrq_key_op *op_p;
	int orig_log_level;
	int orig_suppress_printk;
	int i;

@@ -592,13 +591,12 @@ void __handle_sysrq(u8 key, bool check_mask)
	rcu_sysrq_start();
	rcu_read_lock();
	/*
	 * Raise the apparent loglevel to maximum so that the sysrq header
	 * is shown to provide the user with positive feedback.  We do not
	 * simply emit this at KERN_EMERG as that would change message
	 * routing in the consumers of /proc/kmsg.
	 * Enter in the force_console context so that sysrq header is shown to
	 * provide the user with positive feedback.  We do not simply emit this
	 * at KERN_EMERG as that would change message routing in the consumers
	 * of /proc/kmsg.
	 */
	orig_log_level = console_loglevel;
	console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
	printk_force_console_enter();

	op_p = __sysrq_get_key_op(key);
	if (op_p) {
@@ -608,11 +606,11 @@ void __handle_sysrq(u8 key, bool check_mask)
		 */
		if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
			pr_info("%s\n", op_p->action_msg);
			console_loglevel = orig_log_level;
			printk_force_console_exit();
			op_p->handler(key);
		} else {
			pr_info("This sysrq operation is disabled.\n");
			console_loglevel = orig_log_level;
			printk_force_console_exit();
		}
	} else {
		pr_info("HELP : ");
@@ -630,7 +628,7 @@ void __handle_sysrq(u8 key, bool check_mask)
			}
		}
		pr_cont("\n");
		console_loglevel = orig_log_level;
		printk_force_console_exit();
	}
	rcu_read_unlock();
	rcu_sysrq_end();
+11 −0
Original line number Diff line number Diff line
@@ -166,6 +166,9 @@ __printf(1, 2) __cold int _printk_deferred(const char *fmt, ...);
extern void __printk_deferred_enter(void);
extern void __printk_deferred_exit(void);

extern void printk_force_console_enter(void);
extern void printk_force_console_exit(void);

/*
 * The printk_deferred_enter/exit macros are available only as a hack for
 * some code paths that need to defer all printk console printing. Interrupts
@@ -229,6 +232,14 @@ static inline void printk_deferred_exit(void)
{
}

static inline void printk_force_console_enter(void)
{
}

static inline void printk_force_console_exit(void)
{
}

static inline int printk_ratelimit(void)
{
	return 0;
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write,

/* Flags for a single printk record. */
enum printk_info_flags {
	/* always show on console, ignore console_loglevel */
	LOG_FORCE_CON	= 1,
	LOG_NEWLINE	= 2,	/* text ended with a newline */
	LOG_CONT	= 8,	/* text is a fragment of a continuation line */
};
@@ -90,6 +92,7 @@ bool printk_percpu_data_ready(void);

void defer_console_output(void);
bool is_printk_legacy_deferred(void);
bool is_printk_force_console(void);

u16 printk_parse_prefix(const char *text, int *level,
			enum printk_info_flags *flags);
+16 −5
Original line number Diff line number Diff line
@@ -1337,11 +1337,11 @@ static void boot_delay_msec(int level)
{
	unsigned long long k;
	unsigned long timeout;
	bool suppress = !is_printk_force_console() &&
			suppress_message_printing(level);

	if ((boot_delay == 0 || system_state >= SYSTEM_RUNNING)
		|| suppress_message_printing(level)) {
	if ((boot_delay == 0 || system_state >= SYSTEM_RUNNING) || suppress)
		return;
	}

	k = (unsigned long long)loops_per_msec * boot_delay;

@@ -2291,6 +2291,9 @@ int vprintk_store(int facility, int level,
	if (dev_info)
		flags |= LOG_NEWLINE;

	if (is_printk_force_console())
		flags |= LOG_FORCE_CON;

	if (flags & LOG_CONT) {
		prb_rec_init_wr(&r, reserve_size);
		if (prb_reserve_in_last(&e, prb, &r, caller_id, PRINTKRB_RECORD_MAX)) {
@@ -2298,6 +2301,9 @@ int vprintk_store(int facility, int level,
						 facility, &flags, fmt, args);
			r.info->text_len += text_len;

			if (flags & LOG_FORCE_CON)
				r.info->flags |= LOG_FORCE_CON;

			if (flags & LOG_NEWLINE) {
				r.info->flags |= LOG_NEWLINE;
				prb_final_commit(&e);
@@ -2965,6 +2971,7 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
	struct printk_info info;
	struct printk_record r;
	size_t len = 0;
	bool force_con;

	/*
	 * Formatting extended messages requires a separate buffer, so use the
@@ -2983,9 +2990,13 @@ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,

	pmsg->seq = r.info->seq;
	pmsg->dropped = r.info->seq - seq;
	force_con = r.info->flags & LOG_FORCE_CON;

	/* Skip record that has level above the console loglevel. */
	if (may_suppress && suppress_message_printing(r.info->level))
	/*
	 * Skip records that are not forced to be printed on consoles and that
	 * has level above the console loglevel.
	 */
	if (!force_con && may_suppress && suppress_message_printing(r.info->level))
		goto out;

	if (is_extended) {
+18 −0
Original line number Diff line number Diff line
@@ -12,6 +12,24 @@

#include "internal.h"

/* Context where printk messages are never suppressed */
static atomic_t force_con;

void printk_force_console_enter(void)
{
	atomic_inc(&force_con);
}

void printk_force_console_exit(void)
{
	atomic_dec(&force_con);
}

bool is_printk_force_console(void)
{
	return atomic_read(&force_con);
}

static DEFINE_PER_CPU(int, printk_context);

/* Can be preempted by NMI. */