Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'netconsole-populate-dynamic-entry-even-if-netpoll-fails'

Breno Leitao says:

====================
netconsole: Populate dynamic entry even if netpoll fails

The current implementation of netconsole removes the entry and fails
entirely if netpoll fails to initialize. This approach is suboptimal, as
it prevents reconfiguration or re-enabling of the target through
configfs.

While this issue might seem minor if it were rare, it actually occurs
frequently when the network module is configured as a loadable module.

In such cases, the network is unavailable when netconsole initializes,
causing netpoll to fail. This failure forces users to reconfigure the
target from scratch, discarding any settings provided via the command
line.

The proposed change would keep the target available in configfs, albeit
in a disabled state. This modification allows users to adjust settings
or simply re-enable the target once the network module has loaded,
providing a more flexible and user-friendly solution.

v2: https://lore.kernel.org/20240819103616.2260006-1-leitao@debian.org
v1: https://lore.kernel.org/20240809161935.3129104-1-leitao@debian.org
====================

Link: https://patch.msgid.link/20240822111051.179850-1-leitao@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+21 -9
+11 -4
drivers/net/netconsole.c
··· 1258 1258 goto fail; 1259 1259 1260 1260 err = netpoll_setup(&nt->np); 1261 - if (err) 1262 - goto fail; 1263 - 1261 + if (err) { 1262 + pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n", 1263 + NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count); 1264 + if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) 1265 + /* only fail if dynamic reconfiguration is set, 1266 + * otherwise, keep the target in the list, but disabled. 1267 + */ 1268 + goto fail; 1269 + } else { 1270 + nt->enabled = true; 1271 + } 1264 1272 populate_configfs_item(nt, cmdline_count); 1265 - nt->enabled = true; 1266 1273 1267 1274 return nt; 1268 1275
+10 -5
net/core/netpoll.c
··· 624 624 const struct net_device_ops *ops; 625 625 int err; 626 626 627 - np->dev = ndev; 628 - strscpy(np->dev_name, ndev->name, IFNAMSIZ); 629 - 630 627 if (ndev->priv_flags & IFF_DISABLE_NETPOLL) { 631 628 np_err(np, "%s doesn't support polling, aborting\n", 632 - np->dev_name); 629 + ndev->name); 633 630 err = -ENOTSUPP; 634 631 goto out; 635 632 } ··· 644 647 645 648 refcount_set(&npinfo->refcnt, 1); 646 649 647 - ops = np->dev->netdev_ops; 650 + ops = ndev->netdev_ops; 648 651 if (ops->ndo_netpoll_setup) { 649 652 err = ops->ndo_netpoll_setup(ndev, npinfo); 650 653 if (err) ··· 655 658 refcount_inc(&npinfo->refcnt); 656 659 } 657 660 661 + np->dev = ndev; 662 + strscpy(np->dev_name, ndev->name, IFNAMSIZ); 658 663 npinfo->netpoll = np; 659 664 660 665 /* last thing to do is link it to the net device structure */ ··· 674 675 int netpoll_setup(struct netpoll *np) 675 676 { 676 677 struct net_device *ndev = NULL; 678 + bool ip_overwritten = false; 677 679 struct in_device *in_dev; 678 680 int err; 679 681 ··· 739 739 } 740 740 741 741 np->local_ip.ip = ifa->ifa_local; 742 + ip_overwritten = true; 742 743 np_info(np, "local IP %pI4\n", &np->local_ip.ip); 743 744 } else { 744 745 #if IS_ENABLED(CONFIG_IPV6) ··· 756 755 !!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL)) 757 756 continue; 758 757 np->local_ip.in6 = ifp->addr; 758 + ip_overwritten = true; 759 759 err = 0; 760 760 break; 761 761 } ··· 787 785 return 0; 788 786 789 787 put: 788 + DEBUG_NET_WARN_ON_ONCE(np->dev); 789 + if (ip_overwritten) 790 + memset(&np->local_ip, 0, sizeof(np->local_ip)); 790 791 netdev_put(ndev, &np->dev_tracker); 791 792 unlock: 792 793 rtnl_unlock();