Commit b2bec7d8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull printk updates from Petr Mladek:

 - New "no_hash_pointers" kernel parameter causes that %p shows raw
   pointer values instead of hashed ones. It is intended only for
   debugging purposes. Misuse is prevented by a fat warning message that
   is inspired by trace_printk().

 - Prevent a possible deadlock when flushing printk_safe buffers during
   panic().

 - Fix performance regression caused by the lockless printk ringbuffer.
   It was visible with huge log buffer and long messages.

 - Documentation fix-up.

* tag 'printk-for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  lib/vsprintf: no_hash_pointers prints all addresses as unhashed
  kselftest: add support for skipped tests
  lib: use KSTM_MODULE_GLOBALS macro in kselftest drivers
  printk: avoid prb_first_valid_seq() where possible
  printk: fix deadlock when kernel panic
  printk: rectify kernel-doc for prb_rec_init_wr()
parents 783955f0 16182ac1
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -3293,6 +3293,21 @@
			in certain environments such as networked servers or
			real-time systems.

	no_hash_pointers
			Force pointers printed to the console or buffers to be
			unhashed.  By default, when a pointer is printed via %p
			format string, that pointer is "hashed", i.e. obscured
			by hashing the pointer value.  This is a security feature
			that hides actual kernel addresses from unprivileged
			users, but it also makes debugging the kernel more
			difficult since unequal pointers can no longer be
			compared.  However, if this command-line option is
			specified, then all normal pointers will have their true
			value printed.  Pointers printed via %pK may still be
			hashed.  This option should only be specified when
			debugging the kernel.  Please do not use on production
			kernels.

	nohibernate	[HIBERNATION] Disable hibernation and resume.

	nohz=		[KNL] Boottime enable/disable dynamic ticks
+18 −10
Original line number Diff line number Diff line
@@ -735,9 +735,9 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
		logbuf_lock_irq();
	}

	if (user->seq < prb_first_valid_seq(prb)) {
	if (r->info->seq != user->seq) {
		/* our last seen message is gone, return error and reset */
		user->seq = prb_first_valid_seq(prb);
		user->seq = r->info->seq;
		ret = -EPIPE;
		logbuf_unlock_irq();
		goto out;
@@ -812,6 +812,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
static __poll_t devkmsg_poll(struct file *file, poll_table *wait)
{
	struct devkmsg_user *user = file->private_data;
	struct printk_info info;
	__poll_t ret = 0;

	if (!user)
@@ -820,9 +821,9 @@ static __poll_t devkmsg_poll(struct file *file, poll_table *wait)
	poll_wait(file, &log_wait, wait);

	logbuf_lock_irq();
	if (prb_read_valid(prb, user->seq, NULL)) {
	if (prb_read_valid_info(prb, user->seq, &info, NULL)) {
		/* return error when data has vanished underneath us */
		if (user->seq < prb_first_valid_seq(prb))
		if (info.seq != user->seq)
			ret = EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI;
		else
			ret = EPOLLIN|EPOLLRDNORM;
@@ -1559,6 +1560,7 @@ static void syslog_clear(void)

int do_syslog(int type, char __user *buf, int len, int source)
{
	struct printk_info info;
	bool clear = false;
	static int saved_console_loglevel = LOGLEVEL_DEFAULT;
	int error;
@@ -1629,9 +1631,14 @@ int do_syslog(int type, char __user *buf, int len, int source)
	/* Number of chars in the log buffer */
	case SYSLOG_ACTION_SIZE_UNREAD:
		logbuf_lock_irq();
		if (syslog_seq < prb_first_valid_seq(prb)) {
		if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) {
			/* No unread messages. */
			logbuf_unlock_irq();
			return 0;
		}
		if (info.seq != syslog_seq) {
			/* messages are gone, move to first one */
			syslog_seq = prb_first_valid_seq(prb);
			syslog_seq = info.seq;
			syslog_partial = 0;
		}
		if (source == SYSLOG_FROM_PROC) {
@@ -1643,7 +1650,6 @@ int do_syslog(int type, char __user *buf, int len, int source)
			error = prb_next_seq(prb) - syslog_seq;
		} else {
			bool time = syslog_partial ? syslog_time : printk_time;
			struct printk_info info;
			unsigned int line_count;
			u64 seq;

@@ -3429,9 +3435,11 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
		goto out;

	logbuf_lock_irqsave(flags);
	if (dumper->cur_seq < prb_first_valid_seq(prb)) {
	if (prb_read_valid_info(prb, dumper->cur_seq, &info, NULL)) {
		if (info.seq != dumper->cur_seq) {
			/* messages are gone, move to first available one */
		dumper->cur_seq = prb_first_valid_seq(prb);
			dumper->cur_seq = info.seq;
		}
	}

	/* last entry */
+1 −1
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ _DEFINE_PRINTKRB(name, descbits, avgtextbits, &_##name##_text[0])
/* Writer Interface */

/**
 * prb_rec_init_wd() - Initialize a buffer for writing records.
 * prb_rec_init_wr() - Initialize a buffer for writing records.
 *
 * @r:             The record to initialize.
 * @text_buf_size: The needed text buffer size.
+12 −4
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ struct printk_safe_seq_buf {
static DEFINE_PER_CPU(struct printk_safe_seq_buf, safe_print_seq);
static DEFINE_PER_CPU(int, printk_context);

static DEFINE_RAW_SPINLOCK(safe_read_lock);

#ifdef CONFIG_PRINTK_NMI
static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq);
#endif
@@ -180,8 +182,6 @@ static void report_message_lost(struct printk_safe_seq_buf *s)
 */
static void __printk_safe_flush(struct irq_work *work)
{
	static raw_spinlock_t read_lock =
		__RAW_SPIN_LOCK_INITIALIZER(read_lock);
	struct printk_safe_seq_buf *s =
		container_of(work, struct printk_safe_seq_buf, work);
	unsigned long flags;
@@ -195,7 +195,7 @@ static void __printk_safe_flush(struct irq_work *work)
	 * different CPUs. This is especially important when printing
	 * a backtrace.
	 */
	raw_spin_lock_irqsave(&read_lock, flags);
	raw_spin_lock_irqsave(&safe_read_lock, flags);

	i = 0;
more:
@@ -232,7 +232,7 @@ static void __printk_safe_flush(struct irq_work *work)

out:
	report_message_lost(s);
	raw_spin_unlock_irqrestore(&read_lock, flags);
	raw_spin_unlock_irqrestore(&safe_read_lock, flags);
}

/**
@@ -278,6 +278,14 @@ void printk_safe_flush_on_panic(void)
		raw_spin_lock_init(&logbuf_lock);
	}

	if (raw_spin_is_locked(&safe_read_lock)) {
		if (num_online_cpus() > 1)
			return;

		debug_locks_off();
		raw_spin_lock_init(&safe_read_lock);
	}

	printk_safe_flush();
}

+1 −2
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@

#include "../tools/testing/selftests/kselftest_module.h"

static unsigned total_tests __initdata;
static unsigned failed_tests __initdata;
KSTM_MODULE_GLOBALS();

static char pbl_buffer[PAGE_SIZE] __initdata;

Loading