mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02: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
|
|
@ -1859,23 +1859,6 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
|
||||||
sysdata_len);
|
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,
|
static void send_msg_udp(struct netconsole_target *nt, const char *msg,
|
||||||
unsigned int len)
|
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;
|
struct netconsole_target *nt;
|
||||||
|
|
||||||
if (oops_only && !oops_in_progress)
|
if (oops_only && !oops_in_progress)
|
||||||
return;
|
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) {
|
list_for_each_entry(nt, &target_list, list) {
|
||||||
if (!nt->extended && nt->state == STATE_ENABLED &&
|
if (nt->extended != extended || nt->state != STATE_ENABLED ||
|
||||||
netif_running(nt->np.dev)) {
|
!netif_running(nt->np.dev))
|
||||||
/*
|
continue;
|
||||||
* We nest this inside the for-each-target loop above
|
|
||||||
* so that we're able to get as much logging out to
|
/* If nbcon_enter_unsafe() fails, just return given netconsole
|
||||||
* at least one target if we die inside here, instead
|
* lost the ownership, and iterating over the targets will not
|
||||||
* of unnecessarily keeping all targets in lock-step.
|
* be able to re-acquire.
|
||||||
*/
|
*/
|
||||||
send_msg_udp(nt, msg, len);
|
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);
|
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 = {
|
static struct console netconsole_ext = {
|
||||||
.name = "netcon_ext",
|
.name = "netcon_ext",
|
||||||
.flags = CON_ENABLED | CON_EXTENDED,
|
.flags = CON_ENABLED | CON_EXTENDED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
|
||||||
.write = write_ext_msg,
|
.write_thread = netconsole_write_ext,
|
||||||
|
.write_atomic = netconsole_write_ext,
|
||||||
|
.device_lock = netconsole_device_lock,
|
||||||
|
.device_unlock = netconsole_device_unlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct console netconsole = {
|
static struct console netconsole = {
|
||||||
.name = "netcon",
|
.name = "netcon",
|
||||||
.flags = CON_ENABLED,
|
.flags = CON_ENABLED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
|
||||||
.write = write_msg,
|
.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)
|
static int __init init_netconsole(void)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user