Skip to content

Commit 1efddc0

Browse files
committed
Merge branch 'net-netconsole-configfs-entries-for-boot-target'
Breno Leitao says: ==================== net: netconsole: configfs entries for boot target There is a limitation in netconsole, where it is impossible to disable or modify the target created from the command line parameter. (netconsole=...). "netconsole" cmdline parameter sets the remote IP, and if the remote IP changes, the machine needs to be rebooted (with the new remote IP set in the command line parameter). This allows the user to modify a target without the need to restart the machine. This functionality sits on top of the dynamic target reconfiguration that is already implemented in netconsole. The way to modify a boot time target is creating special named configfs directories, that will be associated with the targets coming from `netconsole=...`. Example: Let's suppose you have two netconsole targets defined at boot time:: netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc;4444@10.0.0.1/eth1,9353@10.0.0.3/12:34:56:78:9a:bc You can modify these targets in runtime by creating the following targets:: $ mkdir cmdline1 $ cat cmdline1/remote_ip 10.0.0.3 $ echo 0 > cmdline1/enabled $ echo 10.0.0.4 > cmdline1/remote_ip $ echo 1 > cmdline1/enabled ==================== Link: https://lore.kernel.org/r/20231012111401.333798-1-leitao@debian.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 220dd22 + 7eeb84d commit 1efddc0

File tree

2 files changed

+121
-56
lines changed

2 files changed

+121
-56
lines changed

Documentation/networking/netconsole.rst

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ Dynamic reconfiguration:
9999
Dynamic reconfigurability is a useful addition to netconsole that enables
100100
remote logging targets to be dynamically added, removed, or have their
101101
parameters reconfigured at runtime from a configfs-based userspace interface.
102-
[ Note that the parameters of netconsole targets that were specified/created
103-
from the boot/module option are not exposed via this interface, and hence
104-
cannot be modified dynamically. ]
105102

106103
To include this feature, select CONFIG_NETCONSOLE_DYNAMIC when building the
107104
netconsole module (or kernel, if netconsole is built-in).
@@ -155,6 +152,25 @@ You can also update the local interface dynamically. This is especially
155152
useful if you want to use interfaces that have newly come up (and may not
156153
have existed when netconsole was loaded / initialized).
157154

155+
Netconsole targets defined at boot time (or module load time) with the
156+
`netconsole=` param are assigned the name `cmdline<index>`. For example, the
157+
first target in the parameter is named `cmdline0`. You can control and modify
158+
these targets by creating configfs directories with the matching name.
159+
160+
Let's suppose you have two netconsole targets defined at boot time::
161+
162+
netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc;4444@10.0.0.1/eth1,9353@10.0.0.3/12:34:56:78:9a:bc
163+
164+
You can modify these targets in runtime by creating the following targets::
165+
166+
mkdir cmdline0
167+
cat cmdline0/remote_ip
168+
10.0.0.2
169+
170+
mkdir cmdline1
171+
cat cmdline1/remote_ip
172+
10.0.0.3
173+
158174
Extended console:
159175
=================
160176

drivers/net/netconsole.c

Lines changed: 102 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ static bool oops_only = false;
5353
module_param(oops_only, bool, 0600);
5454
MODULE_PARM_DESC(oops_only, "Only log oops messages");
5555

56+
#define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
57+
5658
#ifndef MODULE
5759
static int __init option_setup(char *opt)
5860
{
@@ -165,6 +167,10 @@ static void netconsole_target_put(struct netconsole_target *nt)
165167
{
166168
}
167169

170+
static void populate_configfs_item(struct netconsole_target *nt,
171+
int cmdline_count)
172+
{
173+
}
168174
#endif /* CONFIG_NETCONSOLE_DYNAMIC */
169175

170176
/* Allocate and initialize with defaults.
@@ -192,58 +198,6 @@ static struct netconsole_target *alloc_and_init(void)
192198
return nt;
193199
}
194200

195-
/* Allocate new target (from boot/module param) and setup netpoll for it */
196-
static struct netconsole_target *alloc_param_target(char *target_config)
197-
{
198-
struct netconsole_target *nt;
199-
int err;
200-
201-
nt = alloc_and_init();
202-
if (!nt) {
203-
err = -ENOMEM;
204-
goto fail;
205-
}
206-
207-
if (*target_config == '+') {
208-
nt->extended = true;
209-
target_config++;
210-
}
211-
212-
if (*target_config == 'r') {
213-
if (!nt->extended) {
214-
pr_err("Netconsole configuration error. Release feature requires extended log message");
215-
err = -EINVAL;
216-
goto fail;
217-
}
218-
nt->release = true;
219-
target_config++;
220-
}
221-
222-
/* Parse parameters and setup netpoll */
223-
err = netpoll_parse_options(&nt->np, target_config);
224-
if (err)
225-
goto fail;
226-
227-
err = netpoll_setup(&nt->np);
228-
if (err)
229-
goto fail;
230-
231-
nt->enabled = true;
232-
233-
return nt;
234-
235-
fail:
236-
kfree(nt);
237-
return ERR_PTR(err);
238-
}
239-
240-
/* Cleanup netpoll for given target (from boot/module param) and free it */
241-
static void free_param_target(struct netconsole_target *nt)
242-
{
243-
netpoll_cleanup(&nt->np);
244-
kfree(nt);
245-
}
246-
247201
#ifdef CONFIG_NETCONSOLE_DYNAMIC
248202

249203
/*
@@ -675,6 +629,23 @@ static const struct config_item_type netconsole_target_type = {
675629
.ct_owner = THIS_MODULE,
676630
};
677631

632+
static struct netconsole_target *find_cmdline_target(const char *name)
633+
{
634+
struct netconsole_target *nt, *ret = NULL;
635+
unsigned long flags;
636+
637+
spin_lock_irqsave(&target_list_lock, flags);
638+
list_for_each_entry(nt, &target_list, list) {
639+
if (!strcmp(nt->item.ci_name, name)) {
640+
ret = nt;
641+
break;
642+
}
643+
}
644+
spin_unlock_irqrestore(&target_list_lock, flags);
645+
646+
return ret;
647+
}
648+
678649
/*
679650
* Group operations and type for netconsole_subsys.
680651
*/
@@ -685,6 +656,17 @@ static struct config_item *make_netconsole_target(struct config_group *group,
685656
struct netconsole_target *nt;
686657
unsigned long flags;
687658

659+
/* Checking if a target by this name was created at boot time. If so,
660+
* attach a configfs entry to that target. This enables dynamic
661+
* control.
662+
*/
663+
if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
664+
strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
665+
nt = find_cmdline_target(name);
666+
if (nt)
667+
return &nt->item;
668+
}
669+
688670
nt = alloc_and_init();
689671
if (!nt)
690672
return ERR_PTR(-ENOMEM);
@@ -740,6 +722,17 @@ static struct configfs_subsystem netconsole_subsys = {
740722
},
741723
};
742724

725+
static void populate_configfs_item(struct netconsole_target *nt,
726+
int cmdline_count)
727+
{
728+
char target_name[16];
729+
730+
snprintf(target_name, sizeof(target_name), "%s%d",
731+
NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
732+
config_item_init_type_name(&nt->item, target_name,
733+
&netconsole_target_type);
734+
}
735+
743736
#endif /* CONFIG_NETCONSOLE_DYNAMIC */
744737

745738
/* Handle network interface device notifications */
@@ -938,6 +931,60 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
938931
spin_unlock_irqrestore(&target_list_lock, flags);
939932
}
940933

934+
/* Allocate new target (from boot/module param) and setup netpoll for it */
935+
static struct netconsole_target *alloc_param_target(char *target_config,
936+
int cmdline_count)
937+
{
938+
struct netconsole_target *nt;
939+
int err;
940+
941+
nt = alloc_and_init();
942+
if (!nt) {
943+
err = -ENOMEM;
944+
goto fail;
945+
}
946+
947+
if (*target_config == '+') {
948+
nt->extended = true;
949+
target_config++;
950+
}
951+
952+
if (*target_config == 'r') {
953+
if (!nt->extended) {
954+
pr_err("Netconsole configuration error. Release feature requires extended log message");
955+
err = -EINVAL;
956+
goto fail;
957+
}
958+
nt->release = true;
959+
target_config++;
960+
}
961+
962+
/* Parse parameters and setup netpoll */
963+
err = netpoll_parse_options(&nt->np, target_config);
964+
if (err)
965+
goto fail;
966+
967+
err = netpoll_setup(&nt->np);
968+
if (err)
969+
goto fail;
970+
971+
populate_configfs_item(nt, cmdline_count);
972+
nt->enabled = true;
973+
974+
return nt;
975+
976+
fail:
977+
kfree(nt);
978+
return ERR_PTR(err);
979+
}
980+
981+
/* Cleanup netpoll for given target (from boot/module param) and free it */
982+
static void free_param_target(struct netconsole_target *nt)
983+
{
984+
netpoll_cleanup(&nt->np);
985+
kfree(nt);
986+
}
987+
941988
static struct console netconsole_ext = {
942989
.name = "netcon_ext",
943990
.flags = CON_ENABLED | CON_EXTENDED,
@@ -954,14 +1001,15 @@ static int __init init_netconsole(void)
9541001
{
9551002
int err;
9561003
struct netconsole_target *nt, *tmp;
1004+
unsigned int count = 0;
9571005
bool extended = false;
9581006
unsigned long flags;
9591007
char *target_config;
9601008
char *input = config;
9611009

9621010
if (strnlen(input, MAX_PARAM_LENGTH)) {
9631011
while ((target_config = strsep(&input, ";"))) {
964-
nt = alloc_param_target(target_config);
1012+
nt = alloc_param_target(target_config, count);
9651013
if (IS_ERR(nt)) {
9661014
err = PTR_ERR(nt);
9671015
goto fail;
@@ -977,6 +1025,7 @@ static int __init init_netconsole(void)
9771025
spin_lock_irqsave(&target_list_lock, flags);
9781026
list_add(&nt->list, &target_list);
9791027
spin_unlock_irqrestore(&target_list_lock, flags);
1028+
count++;
9801029
}
9811030
}
9821031

0 commit comments

Comments
 (0)