Commit a2293277 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'printk-for-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux

Pull printk updates from Petr Mladek:

 - Remove some twists in the console registration code. It does not
   change the existing behavior except for one corner case. The proper
   default console (with tty binding) will be registered again even when
   it has been removed in the meantime. It is actually a bug fix.
   Anyway, this modified behavior requires some manual interaction.

 - Optimize gdb extension for huge ring buffers.

 - Do not use atomic operations for a local bitmap variable.

 - Update git links in MAINTAINERS.

* tag 'printk-for-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  MAINTAIERS/printk: Add link to printk git
  MAINTAINERS/vsprintf: Update link to printk git tree
  scripts/gdb: lx-dmesg: read records individually
  printk/console: Clean up boot console handling in register_console()
  printk/console: Remove need_default_console variable
  printk/console: Remove unnecessary need_default_console manipulation
  printk/console: Rename has_preferred_console to need_default_console
  printk/console: Split out code that enables default console
  vsprintf: Use non-atomic bitmap API when applicable
parents e9e64f85 d12013c8
...@@ -15396,6 +15396,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org> ...@@ -15396,6 +15396,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org>
R: Steven Rostedt <rostedt@goodmis.org> R: Steven Rostedt <rostedt@goodmis.org>
R: John Ogness <john.ogness@linutronix.de> R: John Ogness <john.ogness@linutronix.de>
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git
F: include/linux/printk.h F: include/linux/printk.h
F: kernel/printk/ F: kernel/printk/
...@@ -20525,7 +20526,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org> ...@@ -20525,7 +20526,7 @@ M: Sergey Senozhatsky <senozhatsky@chromium.org>
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com> R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
R: Rasmus Villemoes <linux@rasmusvillemoes.dk> R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git
F: Documentation/core-api/printk-formats.rst F: Documentation/core-api/printk-formats.rst
F: lib/test_printf.c F: lib/test_printf.c
F: lib/test_scanf.c F: lib/test_scanf.c
......
...@@ -280,7 +280,6 @@ static struct console *exclusive_console; ...@@ -280,7 +280,6 @@ static struct console *exclusive_console;
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
static int preferred_console = -1; static int preferred_console = -1;
static bool has_preferred_console;
int console_set_on_cmdline; int console_set_on_cmdline;
EXPORT_SYMBOL(console_set_on_cmdline); EXPORT_SYMBOL(console_set_on_cmdline);
...@@ -2861,7 +2860,8 @@ early_param("keep_bootcon", keep_bootcon_setup); ...@@ -2861,7 +2860,8 @@ early_param("keep_bootcon", keep_bootcon_setup);
* Care need to be taken with consoles that are statically * Care need to be taken with consoles that are statically
* enabled such as netconsole * enabled such as netconsole
*/ */
static int try_enable_new_console(struct console *newcon, bool user_specified) static int try_enable_preferred_console(struct console *newcon,
bool user_specified)
{ {
struct console_cmdline *c; struct console_cmdline *c;
int i, err; int i, err;
...@@ -2891,10 +2891,8 @@ static int try_enable_new_console(struct console *newcon, bool user_specified) ...@@ -2891,10 +2891,8 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
return err; return err;
} }
newcon->flags |= CON_ENABLED; newcon->flags |= CON_ENABLED;
if (i == preferred_console) { if (i == preferred_console)
newcon->flags |= CON_CONSDEV; newcon->flags |= CON_CONSDEV;
has_preferred_console = true;
}
return 0; return 0;
} }
...@@ -2909,6 +2907,21 @@ static int try_enable_new_console(struct console *newcon, bool user_specified) ...@@ -2909,6 +2907,21 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
return -ENOENT; return -ENOENT;
} }
/* Try to enable the console unconditionally */
static void try_enable_default_console(struct console *newcon)
{
if (newcon->index < 0)
newcon->index = 0;
if (newcon->setup && newcon->setup(newcon, NULL) != 0)
return;
newcon->flags |= CON_ENABLED;
if (newcon->device)
newcon->flags |= CON_CONSDEV;
}
/* /*
* The console driver calls this routine during kernel initialization * The console driver calls this routine during kernel initialization
* to register the console printing procedure with printk() and to * to register the console printing procedure with printk() and to
...@@ -2930,59 +2943,56 @@ static int try_enable_new_console(struct console *newcon, bool user_specified) ...@@ -2930,59 +2943,56 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
*/ */
void register_console(struct console *newcon) void register_console(struct console *newcon)
{ {
struct console *bcon = NULL; struct console *con;
bool bootcon_enabled = false;
bool realcon_enabled = false;
int err; int err;
for_each_console(bcon) { for_each_console(con) {
if (WARN(bcon == newcon, "console '%s%d' already registered\n", if (WARN(con == newcon, "console '%s%d' already registered\n",
bcon->name, bcon->index)) con->name, con->index))
return; return;
} }
/* for_each_console(con) {
* before we register a new CON_BOOT console, make sure we don't if (con->flags & CON_BOOT)
* already have a valid console bootcon_enabled = true;
*/ else
if (newcon->flags & CON_BOOT) { realcon_enabled = true;
for_each_console(bcon) {
if (!(bcon->flags & CON_BOOT)) {
pr_info("Too late to register bootconsole %s%d\n",
newcon->name, newcon->index);
return;
}
}
} }
if (console_drivers && console_drivers->flags & CON_BOOT) /* Do not register boot consoles when there already is a real one. */
bcon = console_drivers; if (newcon->flags & CON_BOOT && realcon_enabled) {
pr_info("Too late to register bootconsole %s%d\n",
if (!has_preferred_console || bcon || !console_drivers) newcon->name, newcon->index);
has_preferred_console = preferred_console >= 0; return;
}
/* /*
* See if we want to use this console driver. If we * See if we want to enable this console driver by default.
* didn't select a console we take the first one *
* that registers here. * Nope when a console is preferred by the command line, device
* tree, or SPCR.
*
* The first real console with tty binding (driver) wins. More
* consoles might get enabled before the right one is found.
*
* Note that a console with tty binding will have CON_CONSDEV
* flag set and will be first in the list.
*/ */
if (!has_preferred_console) { if (preferred_console < 0) {
if (newcon->index < 0) if (!console_drivers || !console_drivers->device ||
newcon->index = 0; console_drivers->flags & CON_BOOT) {
if (newcon->setup == NULL || try_enable_default_console(newcon);
newcon->setup(newcon, NULL) == 0) {
newcon->flags |= CON_ENABLED;
if (newcon->device) {
newcon->flags |= CON_CONSDEV;
has_preferred_console = true;
}
} }
} }
/* See if this console matches one we selected on the command line */ /* See if this console matches one we selected on the command line */
err = try_enable_new_console(newcon, true); err = try_enable_preferred_console(newcon, true);
/* If not, try to match against the platform default(s) */ /* If not, try to match against the platform default(s) */
if (err == -ENOENT) if (err == -ENOENT)
err = try_enable_new_console(newcon, false); err = try_enable_preferred_console(newcon, false);
/* printk() messages are not printed to the Braille console. */ /* printk() messages are not printed to the Braille console. */
if (err || newcon->flags & CON_BRL) if (err || newcon->flags & CON_BRL)
...@@ -2994,8 +3004,10 @@ void register_console(struct console *newcon) ...@@ -2994,8 +3004,10 @@ void register_console(struct console *newcon)
* the real console are the same physical device, it's annoying to * the real console are the same physical device, it's annoying to
* see the beginning boot messages twice * see the beginning boot messages twice
*/ */
if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) if (bootcon_enabled &&
((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) {
newcon->flags &= ~CON_PRINTBUFFER; newcon->flags &= ~CON_PRINTBUFFER;
}
/* /*
* Put this console in the list - keep the * Put this console in the list - keep the
...@@ -3051,15 +3063,15 @@ void register_console(struct console *newcon) ...@@ -3051,15 +3063,15 @@ void register_console(struct console *newcon)
pr_info("%sconsole [%s%d] enabled\n", pr_info("%sconsole [%s%d] enabled\n",
(newcon->flags & CON_BOOT) ? "boot" : "" , (newcon->flags & CON_BOOT) ? "boot" : "" ,
newcon->name, newcon->index); newcon->name, newcon->index);
if (bcon && if (bootcon_enabled &&
((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
!keep_bootcon) { !keep_bootcon) {
/* We need to iterate through all boot consoles, to make /* We need to iterate through all boot consoles, to make
* sure we print everything out, before we unregister them. * sure we print everything out, before we unregister them.
*/ */
for_each_console(bcon) for_each_console(con)
if (bcon->flags & CON_BOOT) if (con->flags & CON_BOOT)
unregister_console(bcon); unregister_console(con);
} }
} }
EXPORT_SYMBOL(register_console); EXPORT_SYMBOL(register_console);
......
...@@ -3564,7 +3564,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) ...@@ -3564,7 +3564,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
++fmt; ++fmt;
for ( ; *fmt && *fmt != ']'; ++fmt, ++len) for ( ; *fmt && *fmt != ']'; ++fmt, ++len)
set_bit((u8)*fmt, set); __set_bit((u8)*fmt, set);
/* no ']' or no character set found */ /* no ']' or no character set found */
if (!*fmt || !len) if (!*fmt || !len)
...@@ -3574,7 +3574,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) ...@@ -3574,7 +3574,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
if (negate) { if (negate) {
bitmap_complement(set, set, 256); bitmap_complement(set, set, 256);
/* exclude null '\0' byte */ /* exclude null '\0' byte */
clear_bit(0, set); __clear_bit(0, set);
} }
/* match must be non-empty */ /* match must be non-empty */
......
...@@ -44,19 +44,17 @@ class LxDmesg(gdb.Command): ...@@ -44,19 +44,17 @@ class LxDmesg(gdb.Command):
sz = prb_desc_ring_type.get_type().sizeof sz = prb_desc_ring_type.get_type().sizeof
desc_ring = utils.read_memoryview(inf, addr, sz).tobytes() desc_ring = utils.read_memoryview(inf, addr, sz).tobytes()
# read in descriptor array # read in descriptor count, size, and address
off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8 off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8
desc_ring_count = 1 << utils.read_u32(desc_ring, off) desc_ring_count = 1 << utils.read_u32(desc_ring, off)
desc_sz = prb_desc_type.get_type().sizeof desc_sz = prb_desc_type.get_type().sizeof
off = prb_desc_ring_type.get_type()['descs'].bitpos // 8 off = prb_desc_ring_type.get_type()['descs'].bitpos // 8
addr = utils.read_ulong(desc_ring, off) desc_addr = utils.read_ulong(desc_ring, off)
descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes()
# read in info array # read in info size and address
info_sz = printk_info_type.get_type().sizeof info_sz = printk_info_type.get_type().sizeof
off = prb_desc_ring_type.get_type()['infos'].bitpos // 8 off = prb_desc_ring_type.get_type()['infos'].bitpos // 8
addr = utils.read_ulong(desc_ring, off) info_addr = utils.read_ulong(desc_ring, off)
infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes()
# read in text data ring structure # read in text data ring structure
off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8
...@@ -64,12 +62,11 @@ class LxDmesg(gdb.Command): ...@@ -64,12 +62,11 @@ class LxDmesg(gdb.Command):
sz = prb_data_ring_type.get_type().sizeof sz = prb_data_ring_type.get_type().sizeof
text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes() text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes()
# read in text data # read in text data size and address
off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8 off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8
text_data_sz = 1 << utils.read_u32(text_data_ring, off) text_data_sz = 1 << utils.read_u32(text_data_ring, off)
off = prb_data_ring_type.get_type()['data'].bitpos // 8 off = prb_data_ring_type.get_type()['data'].bitpos // 8
addr = utils.read_ulong(text_data_ring, off) text_data_addr = utils.read_ulong(text_data_ring, off)
text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes()
counter_off = atomic_long_type.get_type()['counter'].bitpos // 8 counter_off = atomic_long_type.get_type()['counter'].bitpos // 8
...@@ -102,17 +99,20 @@ class LxDmesg(gdb.Command): ...@@ -102,17 +99,20 @@ class LxDmesg(gdb.Command):
desc_off = desc_sz * ind desc_off = desc_sz * ind
info_off = info_sz * ind info_off = info_sz * ind
desc = utils.read_memoryview(inf, desc_addr + desc_off, desc_sz).tobytes()
# skip non-committed record # skip non-committed record
state = 3 & (utils.read_u64(descs, desc_off + sv_off + state = 3 & (utils.read_u64(desc, sv_off + counter_off) >> desc_flags_shift)
counter_off) >> desc_flags_shift)
if state != desc_committed and state != desc_finalized: if state != desc_committed and state != desc_finalized:
if did == head_id: if did == head_id:
break break
did = (did + 1) & desc_id_mask did = (did + 1) & desc_id_mask
continue continue
begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz begin = utils.read_ulong(desc, begin_off) % text_data_sz
end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz end = utils.read_ulong(desc, next_off) % text_data_sz
info = utils.read_memoryview(inf, info_addr + info_off, info_sz).tobytes()
# handle data-less record # handle data-less record
if begin & 1 == 1: if begin & 1 == 1:
...@@ -125,16 +125,17 @@ class LxDmesg(gdb.Command): ...@@ -125,16 +125,17 @@ class LxDmesg(gdb.Command):
# skip over descriptor id # skip over descriptor id
text_start = begin + utils.get_long_type().sizeof text_start = begin + utils.get_long_type().sizeof
text_len = utils.read_u16(infos, info_off + len_off) text_len = utils.read_u16(info, len_off)
# handle truncated message # handle truncated message
if end - text_start < text_len: if end - text_start < text_len:
text_len = end - text_start text_len = end - text_start
text = text_data[text_start:text_start + text_len].decode( text_data = utils.read_memoryview(inf, text_data_addr + text_start,
encoding='utf8', errors='replace') text_len).tobytes()
text = text_data[0:text_len].decode(encoding='utf8', errors='replace')
time_stamp = utils.read_u64(infos, info_off + ts_off) time_stamp = utils.read_u64(info, ts_off)
for line in text.splitlines(): for line in text.splitlines():
msg = u"[{time:12.6f}] {line}\n".format( msg = u"[{time:12.6f}] {line}\n".format(
......
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