mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:24:31 +01:00
netconsole: convert to NBCON console infrastructure
Convert netconsole from the legacy console API to the NBCON framework.
NBCON provides threaded printing which unblocks printk()s and flushes in
a thread, decoupling network TX from printk() when netconsole is
in use.
Since netconsole relies on the network stack which cannot safely operate
from all atomic contexts, mark both consoles with
CON_NBCON_ATOMIC_UNSAFE. (See discussion in [1])
CON_NBCON_ATOMIC_UNSAFE restricts write_atomic() usage to emergency
scenarios (panic) where regular messages are sent in threaded mode.
Implementation changes:
- Unify write_ext_msg() and write_msg() into netconsole_write()
- Add device_lock/device_unlock callbacks to manage target_list_lock
- Use nbcon_enter_unsafe()/nbcon_exit_unsafe() around network
operations.
- If nbcon_enter_unsafe() fails, just return given netconsole lost
the ownership of the console.
- Set write_thread and write_atomic callbacks (both use same function)
Link: https://lore.kernel.org/all/b2qps3uywhmjaym4mht2wpxul4yqtuuayeoq4iv4k3zf5wdgh3@tocu6c7mj4lt/ [1]
Reviewed-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260206-nbcon-v7-3-62bda69b1b41@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
eaf35bc63b
commit
7eab73b186
1 changed files with 62 additions and 39 deletions
|
|
@ -1859,23 +1859,6 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
|
|||
sysdata_len);
|
||||
}
|
||||
|
||||
static void write_ext_msg(struct console *con, const char *msg,
|
||||
unsigned int len)
|
||||
{
|
||||
struct netconsole_target *nt;
|
||||
unsigned long flags;
|
||||
|
||||
if ((oops_only && !oops_in_progress) || list_empty(&target_list))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&target_list_lock, flags);
|
||||
list_for_each_entry(nt, &target_list, list)
|
||||
if (nt->extended && nt->state == STATE_ENABLED &&
|
||||
netif_running(nt->np.dev))
|
||||
send_ext_msg_udp(nt, msg, len);
|
||||
spin_unlock_irqrestore(&target_list_lock, flags);
|
||||
}
|
||||
|
||||
static void send_msg_udp(struct netconsole_target *nt, const char *msg,
|
||||
unsigned int len)
|
||||
{
|
||||
|
|
@ -1890,30 +1873,64 @@ static void send_msg_udp(struct netconsole_target *nt, const char *msg,
|
|||
}
|
||||
}
|
||||
|
||||
static void write_msg(struct console *con, const char *msg, unsigned int len)
|
||||
/**
|
||||
* netconsole_write - Generic function to send a msg to all targets
|
||||
* @wctxt: nbcon write context
|
||||
* @extended: "true" for extended console mode
|
||||
*
|
||||
* Given an nbcon write context, send the message to the netconsole targets
|
||||
*/
|
||||
static void netconsole_write(struct nbcon_write_context *wctxt, bool extended)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct netconsole_target *nt;
|
||||
|
||||
if (oops_only && !oops_in_progress)
|
||||
return;
|
||||
/* Avoid taking lock and disabling interrupts unnecessarily */
|
||||
if (list_empty(&target_list))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&target_list_lock, flags);
|
||||
list_for_each_entry(nt, &target_list, list) {
|
||||
if (!nt->extended && nt->state == STATE_ENABLED &&
|
||||
netif_running(nt->np.dev)) {
|
||||
/*
|
||||
* We nest this inside the for-each-target loop above
|
||||
* so that we're able to get as much logging out to
|
||||
* at least one target if we die inside here, instead
|
||||
* of unnecessarily keeping all targets in lock-step.
|
||||
*/
|
||||
send_msg_udp(nt, msg, len);
|
||||
}
|
||||
if (nt->extended != extended || nt->state != STATE_ENABLED ||
|
||||
!netif_running(nt->np.dev))
|
||||
continue;
|
||||
|
||||
/* If nbcon_enter_unsafe() fails, just return given netconsole
|
||||
* lost the ownership, and iterating over the targets will not
|
||||
* be able to re-acquire.
|
||||
*/
|
||||
if (!nbcon_enter_unsafe(wctxt))
|
||||
return;
|
||||
|
||||
if (extended)
|
||||
send_ext_msg_udp(nt, wctxt->outbuf, wctxt->len);
|
||||
else
|
||||
send_msg_udp(nt, wctxt->outbuf, wctxt->len);
|
||||
|
||||
nbcon_exit_unsafe(wctxt);
|
||||
}
|
||||
}
|
||||
|
||||
static void netconsole_write_ext(struct console *con __always_unused,
|
||||
struct nbcon_write_context *wctxt)
|
||||
{
|
||||
netconsole_write(wctxt, true);
|
||||
}
|
||||
|
||||
static void netconsole_write_basic(struct console *con __always_unused,
|
||||
struct nbcon_write_context *wctxt)
|
||||
{
|
||||
netconsole_write(wctxt, false);
|
||||
}
|
||||
|
||||
static void netconsole_device_lock(struct console *con __always_unused,
|
||||
unsigned long *flags)
|
||||
__acquires(&target_list_lock)
|
||||
{
|
||||
spin_lock_irqsave(&target_list_lock, *flags);
|
||||
}
|
||||
|
||||
static void netconsole_device_unlock(struct console *con __always_unused,
|
||||
unsigned long flags)
|
||||
__releases(&target_list_lock)
|
||||
{
|
||||
spin_unlock_irqrestore(&target_list_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -2077,15 +2094,21 @@ static void free_param_target(struct netconsole_target *nt)
|
|||
}
|
||||
|
||||
static struct console netconsole_ext = {
|
||||
.name = "netcon_ext",
|
||||
.flags = CON_ENABLED | CON_EXTENDED,
|
||||
.write = write_ext_msg,
|
||||
.name = "netcon_ext",
|
||||
.flags = CON_ENABLED | CON_EXTENDED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
|
||||
.write_thread = netconsole_write_ext,
|
||||
.write_atomic = netconsole_write_ext,
|
||||
.device_lock = netconsole_device_lock,
|
||||
.device_unlock = netconsole_device_unlock,
|
||||
};
|
||||
|
||||
static struct console netconsole = {
|
||||
.name = "netcon",
|
||||
.flags = CON_ENABLED,
|
||||
.write = write_msg,
|
||||
.name = "netcon",
|
||||
.flags = CON_ENABLED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
|
||||
.write_thread = netconsole_write_basic,
|
||||
.write_atomic = netconsole_write_basic,
|
||||
.device_lock = netconsole_device_lock,
|
||||
.device_unlock = netconsole_device_unlock,
|
||||
};
|
||||
|
||||
static int __init init_netconsole(void)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue