Skip to content

Commit 7eab73b

Browse files
leitaokuba-moo
authored andcommitted
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>
1 parent eaf35bc commit 7eab73b

1 file changed

Lines changed: 62 additions & 39 deletions

File tree

drivers/net/netconsole.c

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,23 +1859,6 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
18591859
sysdata_len);
18601860
}
18611861

1862-
static void write_ext_msg(struct console *con, const char *msg,
1863-
unsigned int len)
1864-
{
1865-
struct netconsole_target *nt;
1866-
unsigned long flags;
1867-
1868-
if ((oops_only && !oops_in_progress) || list_empty(&target_list))
1869-
return;
1870-
1871-
spin_lock_irqsave(&target_list_lock, flags);
1872-
list_for_each_entry(nt, &target_list, list)
1873-
if (nt->extended && nt->state == STATE_ENABLED &&
1874-
netif_running(nt->np.dev))
1875-
send_ext_msg_udp(nt, msg, len);
1876-
spin_unlock_irqrestore(&target_list_lock, flags);
1877-
}
1878-
18791862
static void send_msg_udp(struct netconsole_target *nt, const char *msg,
18801863
unsigned int len)
18811864
{
@@ -1890,30 +1873,64 @@ static void send_msg_udp(struct netconsole_target *nt, const char *msg,
18901873
}
18911874
}
18921875

1893-
static void write_msg(struct console *con, const char *msg, unsigned int len)
1876+
/**
1877+
* netconsole_write - Generic function to send a msg to all targets
1878+
* @wctxt: nbcon write context
1879+
* @extended: "true" for extended console mode
1880+
*
1881+
* Given an nbcon write context, send the message to the netconsole targets
1882+
*/
1883+
static void netconsole_write(struct nbcon_write_context *wctxt, bool extended)
18941884
{
1895-
unsigned long flags;
18961885
struct netconsole_target *nt;
18971886

18981887
if (oops_only && !oops_in_progress)
18991888
return;
1900-
/* Avoid taking lock and disabling interrupts unnecessarily */
1901-
if (list_empty(&target_list))
1902-
return;
19031889

1904-
spin_lock_irqsave(&target_list_lock, flags);
19051890
list_for_each_entry(nt, &target_list, list) {
1906-
if (!nt->extended && nt->state == STATE_ENABLED &&
1907-
netif_running(nt->np.dev)) {
1908-
/*
1909-
* We nest this inside the for-each-target loop above
1910-
* so that we're able to get as much logging out to
1911-
* at least one target if we die inside here, instead
1912-
* of unnecessarily keeping all targets in lock-step.
1913-
*/
1914-
send_msg_udp(nt, msg, len);
1915-
}
1891+
if (nt->extended != extended || nt->state != STATE_ENABLED ||
1892+
!netif_running(nt->np.dev))
1893+
continue;
1894+
1895+
/* If nbcon_enter_unsafe() fails, just return given netconsole
1896+
* lost the ownership, and iterating over the targets will not
1897+
* be able to re-acquire.
1898+
*/
1899+
if (!nbcon_enter_unsafe(wctxt))
1900+
return;
1901+
1902+
if (extended)
1903+
send_ext_msg_udp(nt, wctxt->outbuf, wctxt->len);
1904+
else
1905+
send_msg_udp(nt, wctxt->outbuf, wctxt->len);
1906+
1907+
nbcon_exit_unsafe(wctxt);
19161908
}
1909+
}
1910+
1911+
static void netconsole_write_ext(struct console *con __always_unused,
1912+
struct nbcon_write_context *wctxt)
1913+
{
1914+
netconsole_write(wctxt, true);
1915+
}
1916+
1917+
static void netconsole_write_basic(struct console *con __always_unused,
1918+
struct nbcon_write_context *wctxt)
1919+
{
1920+
netconsole_write(wctxt, false);
1921+
}
1922+
1923+
static void netconsole_device_lock(struct console *con __always_unused,
1924+
unsigned long *flags)
1925+
__acquires(&target_list_lock)
1926+
{
1927+
spin_lock_irqsave(&target_list_lock, *flags);
1928+
}
1929+
1930+
static void netconsole_device_unlock(struct console *con __always_unused,
1931+
unsigned long flags)
1932+
__releases(&target_list_lock)
1933+
{
19171934
spin_unlock_irqrestore(&target_list_lock, flags);
19181935
}
19191936

@@ -2077,15 +2094,21 @@ static void free_param_target(struct netconsole_target *nt)
20772094
}
20782095

20792096
static struct console netconsole_ext = {
2080-
.name = "netcon_ext",
2081-
.flags = CON_ENABLED | CON_EXTENDED,
2082-
.write = write_ext_msg,
2097+
.name = "netcon_ext",
2098+
.flags = CON_ENABLED | CON_EXTENDED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
2099+
.write_thread = netconsole_write_ext,
2100+
.write_atomic = netconsole_write_ext,
2101+
.device_lock = netconsole_device_lock,
2102+
.device_unlock = netconsole_device_unlock,
20832103
};
20842104

20852105
static struct console netconsole = {
2086-
.name = "netcon",
2087-
.flags = CON_ENABLED,
2088-
.write = write_msg,
2106+
.name = "netcon",
2107+
.flags = CON_ENABLED | CON_NBCON | CON_NBCON_ATOMIC_UNSAFE,
2108+
.write_thread = netconsole_write_basic,
2109+
.write_atomic = netconsole_write_basic,
2110+
.device_lock = netconsole_device_lock,
2111+
.device_unlock = netconsole_device_unlock,
20892112
};
20902113

20912114
static int __init init_netconsole(void)

0 commit comments

Comments
 (0)