1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * linux/drivers/net/netconsole.c
4 *
5 * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
6 *
7 * This file contains the implementation of an IRQ-safe, crash-safe
8 * kernel console implementation that outputs kernel messages to the
9 * network.
10 *
11 * Modification history:
12 *
13 * 2001-09-17 started by Ingo Molnar.
14 * 2003-08-11 2.6 port by Matt Mackall
15 * simplified options
16 * generic card hooks
17 * works non-modular
18 * 2003-09-07 rewritten with netpoll api
19 */
20
21 /****************************************************************
22 *
23 ****************************************************************/
24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27 #include <linux/mm.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/console.h>
32 #include <linux/moduleparam.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/netpoll.h>
36 #include <linux/inet.h>
37 #include <linux/configfs.h>
38 #include <linux/etherdevice.h>
39 #include <linux/u64_stats_sync.h>
40 #include <linux/utsname.h>
41 #include <linux/rtnetlink.h>
42
43 MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
44 MODULE_DESCRIPTION("Console driver for network interfaces");
45 MODULE_LICENSE("GPL");
46
47 #define MAX_PARAM_LENGTH 256
48 #define MAX_EXTRADATA_ENTRY_LEN 256
49 #define MAX_EXTRADATA_VALUE_LEN 200
50 /* The number 3 comes from userdata entry format characters (' ', '=', '\n') */
51 #define MAX_EXTRADATA_NAME_LEN (MAX_EXTRADATA_ENTRY_LEN - \
52 MAX_EXTRADATA_VALUE_LEN - 3)
53 #define MAX_USERDATA_ITEMS 256
54 #define MAX_PRINT_CHUNK 1000
55
56 static char config[MAX_PARAM_LENGTH];
57 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
58 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
59
60 static bool oops_only;
61 module_param(oops_only, bool, 0600);
62 MODULE_PARM_DESC(oops_only, "Only log oops messages");
63
64 #define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
65
66 #ifndef MODULE
option_setup(char * opt)67 static int __init option_setup(char *opt)
68 {
69 strscpy(config, opt, MAX_PARAM_LENGTH);
70 return 1;
71 }
72 __setup("netconsole=", option_setup);
73 #endif /* MODULE */
74
75 /* Linked list of all configured targets */
76 static LIST_HEAD(target_list);
77 /* target_cleanup_list is used to track targets that need to be cleaned outside
78 * of target_list_lock. It should be cleaned in the same function it is
79 * populated.
80 */
81 static LIST_HEAD(target_cleanup_list);
82
83 /* This needs to be a spinlock because write_msg() cannot sleep */
84 static DEFINE_SPINLOCK(target_list_lock);
85 /* This needs to be a mutex because netpoll_cleanup might sleep */
86 static DEFINE_MUTEX(target_cleanup_list_lock);
87
88 /*
89 * Console driver for netconsoles. Register only consoles that have
90 * an associated target of the same type.
91 */
92 static struct console netconsole_ext, netconsole;
93
94 struct netconsole_target_stats {
95 u64_stats_t xmit_drop_count;
96 u64_stats_t enomem_count;
97 struct u64_stats_sync syncp;
98 };
99
100 enum console_type {
101 CONS_BASIC = BIT(0),
102 CONS_EXTENDED = BIT(1),
103 };
104
105 /* Features enabled in sysdata. Contrary to userdata, this data is populated by
106 * the kernel. The fields are designed as bitwise flags, allowing multiple
107 * features to be set in sysdata_fields.
108 */
109 enum sysdata_feature {
110 /* Populate the CPU that sends the message */
111 SYSDATA_CPU_NR = BIT(0),
112 /* Populate the task name (as in current->comm) in sysdata */
113 SYSDATA_TASKNAME = BIT(1),
114 /* Kernel release/version as part of sysdata */
115 SYSDATA_RELEASE = BIT(2),
116 /* Include a per-target message ID as part of sysdata */
117 SYSDATA_MSGID = BIT(3),
118 /* Sentinel: highest bit position */
119 MAX_SYSDATA_ITEMS = 4,
120 };
121
122 /**
123 * struct netconsole_target - Represents a configured netconsole target.
124 * @list: Links this target into the target_list.
125 * @group: Links us into the configfs subsystem hierarchy.
126 * @userdata_group: Links to the userdata configfs hierarchy
127 * @userdata: Cached, formatted string of append
128 * @userdata_length: String length of userdata.
129 * @sysdata: Cached, formatted string of append
130 * @sysdata_fields: Sysdata features enabled.
131 * @msgcounter: Message sent counter.
132 * @stats: Packet send stats for the target. Used for debugging.
133 * @enabled: On / off knob to enable / disable target.
134 * Visible from userspace (read-write).
135 * We maintain a strict 1:1 correspondence between this and
136 * whether the corresponding netpoll is active or inactive.
137 * Also, other parameters of a target may be modified at
138 * runtime only when it is disabled (enabled == 0).
139 * @extended: Denotes whether console is extended or not.
140 * @release: Denotes whether kernel release version should be prepended
141 * to the message. Depends on extended console.
142 * @np: The netpoll structure for this target.
143 * Contains the other userspace visible parameters:
144 * dev_name (read-write)
145 * local_port (read-write)
146 * remote_port (read-write)
147 * local_ip (read-write)
148 * remote_ip (read-write)
149 * local_mac (read-only)
150 * remote_mac (read-write)
151 * @buf: The buffer used to send the full msg to the network stack
152 */
153 struct netconsole_target {
154 struct list_head list;
155 #ifdef CONFIG_NETCONSOLE_DYNAMIC
156 struct config_group group;
157 struct config_group userdata_group;
158 char *userdata;
159 size_t userdata_length;
160 char sysdata[MAX_EXTRADATA_ENTRY_LEN * MAX_SYSDATA_ITEMS];
161
162 /* bit-wise with sysdata_feature bits */
163 u32 sysdata_fields;
164 /* protected by target_list_lock */
165 u32 msgcounter;
166 #endif
167 struct netconsole_target_stats stats;
168 bool enabled;
169 bool extended;
170 bool release;
171 struct netpoll np;
172 /* protected by target_list_lock */
173 char buf[MAX_PRINT_CHUNK];
174 };
175
176 #ifdef CONFIG_NETCONSOLE_DYNAMIC
177
178 static struct configfs_subsystem netconsole_subsys;
179 static DEFINE_MUTEX(dynamic_netconsole_mutex);
180
dynamic_netconsole_init(void)181 static int __init dynamic_netconsole_init(void)
182 {
183 config_group_init(&netconsole_subsys.su_group);
184 mutex_init(&netconsole_subsys.su_mutex);
185 return configfs_register_subsystem(&netconsole_subsys);
186 }
187
dynamic_netconsole_exit(void)188 static void __exit dynamic_netconsole_exit(void)
189 {
190 configfs_unregister_subsystem(&netconsole_subsys);
191 }
192
193 /*
194 * Targets that were created by parsing the boot/module option string
195 * do not exist in the configfs hierarchy (and have NULL names) and will
196 * never go away, so make these a no-op for them.
197 */
netconsole_target_get(struct netconsole_target * nt)198 static void netconsole_target_get(struct netconsole_target *nt)
199 {
200 if (config_item_name(&nt->group.cg_item))
201 config_group_get(&nt->group);
202 }
203
netconsole_target_put(struct netconsole_target * nt)204 static void netconsole_target_put(struct netconsole_target *nt)
205 {
206 if (config_item_name(&nt->group.cg_item))
207 config_group_put(&nt->group);
208 }
209
210 #else /* !CONFIG_NETCONSOLE_DYNAMIC */
211
dynamic_netconsole_init(void)212 static int __init dynamic_netconsole_init(void)
213 {
214 return 0;
215 }
216
dynamic_netconsole_exit(void)217 static void __exit dynamic_netconsole_exit(void)
218 {
219 }
220
221 /*
222 * No danger of targets going away from under us when dynamic
223 * reconfigurability is off.
224 */
netconsole_target_get(struct netconsole_target * nt)225 static void netconsole_target_get(struct netconsole_target *nt)
226 {
227 }
228
netconsole_target_put(struct netconsole_target * nt)229 static void netconsole_target_put(struct netconsole_target *nt)
230 {
231 }
232
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)233 static void populate_configfs_item(struct netconsole_target *nt,
234 int cmdline_count)
235 {
236 }
237 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
238
239 /* Allocate and initialize with defaults.
240 * Note that these targets get their config_item fields zeroed-out.
241 */
alloc_and_init(void)242 static struct netconsole_target *alloc_and_init(void)
243 {
244 struct netconsole_target *nt;
245
246 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
247 if (!nt)
248 return nt;
249
250 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))
251 nt->extended = true;
252 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))
253 nt->release = true;
254
255 nt->np.name = "netconsole";
256 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
257 nt->np.local_port = 6665;
258 nt->np.remote_port = 6666;
259 eth_broadcast_addr(nt->np.remote_mac);
260
261 return nt;
262 }
263
264 /* Clean up every target in the cleanup_list and move the clean targets back to
265 * the main target_list.
266 */
netconsole_process_cleanups_core(void)267 static void netconsole_process_cleanups_core(void)
268 {
269 struct netconsole_target *nt, *tmp;
270 unsigned long flags;
271
272 /* The cleanup needs RTNL locked */
273 ASSERT_RTNL();
274
275 mutex_lock(&target_cleanup_list_lock);
276 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {
277 /* all entries in the cleanup_list needs to be disabled */
278 WARN_ON_ONCE(nt->enabled);
279 do_netpoll_cleanup(&nt->np);
280 /* moved the cleaned target to target_list. Need to hold both
281 * locks
282 */
283 spin_lock_irqsave(&target_list_lock, flags);
284 list_move(&nt->list, &target_list);
285 spin_unlock_irqrestore(&target_list_lock, flags);
286 }
287 WARN_ON_ONCE(!list_empty(&target_cleanup_list));
288 mutex_unlock(&target_cleanup_list_lock);
289 }
290
netconsole_print_banner(struct netpoll * np)291 static void netconsole_print_banner(struct netpoll *np)
292 {
293 np_info(np, "local port %d\n", np->local_port);
294 if (np->ipv6)
295 np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
296 else
297 np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
298 np_info(np, "interface name '%s'\n", np->dev_name);
299 np_info(np, "local ethernet address '%pM'\n", np->dev_mac);
300 np_info(np, "remote port %d\n", np->remote_port);
301 if (np->ipv6)
302 np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
303 else
304 np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
305 np_info(np, "remote ethernet address %pM\n", np->remote_mac);
306 }
307
308 /* Parse the string and populate the `inet_addr` union. Return 0 if IPv4 is
309 * populated, 1 if IPv6 is populated, and -1 upon failure.
310 */
netpoll_parse_ip_addr(const char * str,union inet_addr * addr)311 static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
312 {
313 const char *end = NULL;
314 int len;
315
316 len = strlen(str);
317 if (!len)
318 return -1;
319
320 if (str[len - 1] == '\n')
321 len -= 1;
322
323 if (in4_pton(str, len, (void *)addr, -1, &end) > 0 &&
324 (!end || *end == 0 || *end == '\n'))
325 return 0;
326
327 if (IS_ENABLED(CONFIG_IPV6) &&
328 in6_pton(str, len, (void *)addr, -1, &end) > 0 &&
329 (!end || *end == 0 || *end == '\n'))
330 return 1;
331
332 return -1;
333 }
334
335 #ifdef CONFIG_NETCONSOLE_DYNAMIC
336
337 /*
338 * Our subsystem hierarchy is:
339 *
340 * /sys/kernel/config/netconsole/
341 * |
342 * <target>/
343 * | enabled
344 * | release
345 * | dev_name
346 * | local_port
347 * | remote_port
348 * | local_ip
349 * | remote_ip
350 * | local_mac
351 * | remote_mac
352 * | transmit_errors
353 * | userdata/
354 * | <key>/
355 * | value
356 * | ...
357 * |
358 * <target>/...
359 */
360
to_target(struct config_item * item)361 static struct netconsole_target *to_target(struct config_item *item)
362 {
363 struct config_group *cfg_group;
364
365 cfg_group = to_config_group(item);
366 if (!cfg_group)
367 return NULL;
368 return container_of(to_config_group(item),
369 struct netconsole_target, group);
370 }
371
372 /* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
373 * netdev might be cleaned-up by calling __netpoll_cleanup(),
374 */
netconsole_process_cleanups(void)375 static void netconsole_process_cleanups(void)
376 {
377 /* rtnl lock is called here, because it has precedence over
378 * target_cleanup_list_lock mutex and target_cleanup_list
379 */
380 rtnl_lock();
381 netconsole_process_cleanups_core();
382 rtnl_unlock();
383 }
384
385 /* Get rid of possible trailing newline, returning the new length */
trim_newline(char * s,size_t maxlen)386 static void trim_newline(char *s, size_t maxlen)
387 {
388 size_t len;
389
390 len = strnlen(s, maxlen);
391 if (s[len - 1] == '\n')
392 s[len - 1] = '\0';
393 }
394
395 /*
396 * Attribute operations for netconsole_target.
397 */
398
enabled_show(struct config_item * item,char * buf)399 static ssize_t enabled_show(struct config_item *item, char *buf)
400 {
401 return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
402 }
403
extended_show(struct config_item * item,char * buf)404 static ssize_t extended_show(struct config_item *item, char *buf)
405 {
406 return sysfs_emit(buf, "%d\n", to_target(item)->extended);
407 }
408
release_show(struct config_item * item,char * buf)409 static ssize_t release_show(struct config_item *item, char *buf)
410 {
411 return sysfs_emit(buf, "%d\n", to_target(item)->release);
412 }
413
dev_name_show(struct config_item * item,char * buf)414 static ssize_t dev_name_show(struct config_item *item, char *buf)
415 {
416 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);
417 }
418
local_port_show(struct config_item * item,char * buf)419 static ssize_t local_port_show(struct config_item *item, char *buf)
420 {
421 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);
422 }
423
remote_port_show(struct config_item * item,char * buf)424 static ssize_t remote_port_show(struct config_item *item, char *buf)
425 {
426 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);
427 }
428
local_ip_show(struct config_item * item,char * buf)429 static ssize_t local_ip_show(struct config_item *item, char *buf)
430 {
431 struct netconsole_target *nt = to_target(item);
432
433 if (nt->np.ipv6)
434 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
435 else
436 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
437 }
438
remote_ip_show(struct config_item * item,char * buf)439 static ssize_t remote_ip_show(struct config_item *item, char *buf)
440 {
441 struct netconsole_target *nt = to_target(item);
442
443 if (nt->np.ipv6)
444 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
445 else
446 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
447 }
448
local_mac_show(struct config_item * item,char * buf)449 static ssize_t local_mac_show(struct config_item *item, char *buf)
450 {
451 struct net_device *dev = to_target(item)->np.dev;
452 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
453
454 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);
455 }
456
remote_mac_show(struct config_item * item,char * buf)457 static ssize_t remote_mac_show(struct config_item *item, char *buf)
458 {
459 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
460 }
461
transmit_errors_show(struct config_item * item,char * buf)462 static ssize_t transmit_errors_show(struct config_item *item, char *buf)
463 {
464 struct netconsole_target *nt = to_target(item);
465 u64 xmit_drop_count, enomem_count;
466 unsigned int start;
467
468 do {
469 start = u64_stats_fetch_begin(&nt->stats.syncp);
470 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
471 enomem_count = u64_stats_read(&nt->stats.enomem_count);
472 } while (u64_stats_fetch_retry(&nt->stats.syncp, start));
473
474 return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
475 }
476
477 /* configfs helper to display if cpu_nr sysdata feature is enabled */
sysdata_cpu_nr_enabled_show(struct config_item * item,char * buf)478 static ssize_t sysdata_cpu_nr_enabled_show(struct config_item *item, char *buf)
479 {
480 struct netconsole_target *nt = to_target(item->ci_parent);
481 bool cpu_nr_enabled;
482
483 mutex_lock(&dynamic_netconsole_mutex);
484 cpu_nr_enabled = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
485 mutex_unlock(&dynamic_netconsole_mutex);
486
487 return sysfs_emit(buf, "%d\n", cpu_nr_enabled);
488 }
489
490 /* configfs helper to display if taskname sysdata feature is enabled */
sysdata_taskname_enabled_show(struct config_item * item,char * buf)491 static ssize_t sysdata_taskname_enabled_show(struct config_item *item,
492 char *buf)
493 {
494 struct netconsole_target *nt = to_target(item->ci_parent);
495 bool taskname_enabled;
496
497 mutex_lock(&dynamic_netconsole_mutex);
498 taskname_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
499 mutex_unlock(&dynamic_netconsole_mutex);
500
501 return sysfs_emit(buf, "%d\n", taskname_enabled);
502 }
503
sysdata_release_enabled_show(struct config_item * item,char * buf)504 static ssize_t sysdata_release_enabled_show(struct config_item *item,
505 char *buf)
506 {
507 struct netconsole_target *nt = to_target(item->ci_parent);
508 bool release_enabled;
509
510 mutex_lock(&dynamic_netconsole_mutex);
511 release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
512 mutex_unlock(&dynamic_netconsole_mutex);
513
514 return sysfs_emit(buf, "%d\n", release_enabled);
515 }
516
517 /* Iterate in the list of target, and make sure we don't have any console
518 * register without targets of the same type
519 */
unregister_netcons_consoles(void)520 static void unregister_netcons_consoles(void)
521 {
522 struct netconsole_target *nt;
523 u32 console_type_needed = 0;
524 unsigned long flags;
525
526 spin_lock_irqsave(&target_list_lock, flags);
527 list_for_each_entry(nt, &target_list, list) {
528 if (nt->extended)
529 console_type_needed |= CONS_EXTENDED;
530 else
531 console_type_needed |= CONS_BASIC;
532 }
533 spin_unlock_irqrestore(&target_list_lock, flags);
534
535 if (!(console_type_needed & CONS_EXTENDED) &&
536 console_is_registered(&netconsole_ext))
537 unregister_console(&netconsole_ext);
538
539 if (!(console_type_needed & CONS_BASIC) &&
540 console_is_registered(&netconsole))
541 unregister_console(&netconsole);
542 }
543
sysdata_msgid_enabled_show(struct config_item * item,char * buf)544 static ssize_t sysdata_msgid_enabled_show(struct config_item *item,
545 char *buf)
546 {
547 struct netconsole_target *nt = to_target(item->ci_parent);
548 bool msgid_enabled;
549
550 mutex_lock(&dynamic_netconsole_mutex);
551 msgid_enabled = !!(nt->sysdata_fields & SYSDATA_MSGID);
552 mutex_unlock(&dynamic_netconsole_mutex);
553
554 return sysfs_emit(buf, "%d\n", msgid_enabled);
555 }
556
557 /*
558 * This one is special -- targets created through the configfs interface
559 * are not enabled (and the corresponding netpoll activated) by default.
560 * The user is expected to set the desired parameters first (which
561 * would enable him to dynamically add new netpoll targets for new
562 * network interfaces as and when they come up).
563 */
enabled_store(struct config_item * item,const char * buf,size_t count)564 static ssize_t enabled_store(struct config_item *item,
565 const char *buf, size_t count)
566 {
567 struct netconsole_target *nt = to_target(item);
568 unsigned long flags;
569 bool enabled;
570 ssize_t ret;
571
572 mutex_lock(&dynamic_netconsole_mutex);
573 ret = kstrtobool(buf, &enabled);
574 if (ret)
575 goto out_unlock;
576
577 ret = -EINVAL;
578 if (enabled == nt->enabled) {
579 pr_info("network logging has already %s\n",
580 nt->enabled ? "started" : "stopped");
581 goto out_unlock;
582 }
583
584 if (enabled) { /* true */
585 if (nt->release && !nt->extended) {
586 pr_err("Not enabling netconsole. Release feature requires extended log message");
587 goto out_unlock;
588 }
589
590 if (nt->extended && !console_is_registered(&netconsole_ext)) {
591 netconsole_ext.flags |= CON_ENABLED;
592 register_console(&netconsole_ext);
593 }
594
595 /* User might be enabling the basic format target for the very
596 * first time, make sure the console is registered.
597 */
598 if (!nt->extended && !console_is_registered(&netconsole)) {
599 netconsole.flags |= CON_ENABLED;
600 register_console(&netconsole);
601 }
602
603 /*
604 * Skip netconsole_parser_cmdline() -- all the attributes are
605 * already configured via configfs. Just print them out.
606 */
607 netconsole_print_banner(&nt->np);
608
609 ret = netpoll_setup(&nt->np);
610 if (ret)
611 goto out_unlock;
612
613 nt->enabled = true;
614 pr_info("network logging started\n");
615 } else { /* false */
616 /* We need to disable the netconsole before cleaning it up
617 * otherwise we might end up in write_msg() with
618 * nt->np.dev == NULL and nt->enabled == true
619 */
620 mutex_lock(&target_cleanup_list_lock);
621 spin_lock_irqsave(&target_list_lock, flags);
622 nt->enabled = false;
623 /* Remove the target from the list, while holding
624 * target_list_lock
625 */
626 list_move(&nt->list, &target_cleanup_list);
627 spin_unlock_irqrestore(&target_list_lock, flags);
628 mutex_unlock(&target_cleanup_list_lock);
629 /* Unregister consoles, whose the last target of that type got
630 * disabled.
631 */
632 unregister_netcons_consoles();
633 }
634
635 ret = strnlen(buf, count);
636 /* Deferred cleanup */
637 netconsole_process_cleanups();
638 out_unlock:
639 mutex_unlock(&dynamic_netconsole_mutex);
640 return ret;
641 }
642
release_store(struct config_item * item,const char * buf,size_t count)643 static ssize_t release_store(struct config_item *item, const char *buf,
644 size_t count)
645 {
646 struct netconsole_target *nt = to_target(item);
647 bool release;
648 ssize_t ret;
649
650 mutex_lock(&dynamic_netconsole_mutex);
651 if (nt->enabled) {
652 pr_err("target (%s) is enabled, disable to update parameters\n",
653 config_item_name(&nt->group.cg_item));
654 ret = -EINVAL;
655 goto out_unlock;
656 }
657
658 ret = kstrtobool(buf, &release);
659 if (ret)
660 goto out_unlock;
661
662 nt->release = release;
663
664 ret = strnlen(buf, count);
665 out_unlock:
666 mutex_unlock(&dynamic_netconsole_mutex);
667 return ret;
668 }
669
extended_store(struct config_item * item,const char * buf,size_t count)670 static ssize_t extended_store(struct config_item *item, const char *buf,
671 size_t count)
672 {
673 struct netconsole_target *nt = to_target(item);
674 bool extended;
675 ssize_t ret;
676
677 mutex_lock(&dynamic_netconsole_mutex);
678 if (nt->enabled) {
679 pr_err("target (%s) is enabled, disable to update parameters\n",
680 config_item_name(&nt->group.cg_item));
681 ret = -EINVAL;
682 goto out_unlock;
683 }
684
685 ret = kstrtobool(buf, &extended);
686 if (ret)
687 goto out_unlock;
688
689 nt->extended = extended;
690 ret = strnlen(buf, count);
691 out_unlock:
692 mutex_unlock(&dynamic_netconsole_mutex);
693 return ret;
694 }
695
dev_name_store(struct config_item * item,const char * buf,size_t count)696 static ssize_t dev_name_store(struct config_item *item, const char *buf,
697 size_t count)
698 {
699 struct netconsole_target *nt = to_target(item);
700
701 mutex_lock(&dynamic_netconsole_mutex);
702 if (nt->enabled) {
703 pr_err("target (%s) is enabled, disable to update parameters\n",
704 config_item_name(&nt->group.cg_item));
705 mutex_unlock(&dynamic_netconsole_mutex);
706 return -EINVAL;
707 }
708
709 strscpy(nt->np.dev_name, buf, IFNAMSIZ);
710 trim_newline(nt->np.dev_name, IFNAMSIZ);
711
712 mutex_unlock(&dynamic_netconsole_mutex);
713 return strnlen(buf, count);
714 }
715
local_port_store(struct config_item * item,const char * buf,size_t count)716 static ssize_t local_port_store(struct config_item *item, const char *buf,
717 size_t count)
718 {
719 struct netconsole_target *nt = to_target(item);
720 ssize_t ret = -EINVAL;
721
722 mutex_lock(&dynamic_netconsole_mutex);
723 if (nt->enabled) {
724 pr_err("target (%s) is enabled, disable to update parameters\n",
725 config_item_name(&nt->group.cg_item));
726 goto out_unlock;
727 }
728
729 ret = kstrtou16(buf, 10, &nt->np.local_port);
730 if (ret < 0)
731 goto out_unlock;
732 ret = strnlen(buf, count);
733 out_unlock:
734 mutex_unlock(&dynamic_netconsole_mutex);
735 return ret;
736 }
737
remote_port_store(struct config_item * item,const char * buf,size_t count)738 static ssize_t remote_port_store(struct config_item *item,
739 const char *buf, size_t count)
740 {
741 struct netconsole_target *nt = to_target(item);
742 ssize_t ret = -EINVAL;
743
744 mutex_lock(&dynamic_netconsole_mutex);
745 if (nt->enabled) {
746 pr_err("target (%s) is enabled, disable to update parameters\n",
747 config_item_name(&nt->group.cg_item));
748 goto out_unlock;
749 }
750
751 ret = kstrtou16(buf, 10, &nt->np.remote_port);
752 if (ret < 0)
753 goto out_unlock;
754 ret = strnlen(buf, count);
755 out_unlock:
756 mutex_unlock(&dynamic_netconsole_mutex);
757 return ret;
758 }
759
local_ip_store(struct config_item * item,const char * buf,size_t count)760 static ssize_t local_ip_store(struct config_item *item, const char *buf,
761 size_t count)
762 {
763 struct netconsole_target *nt = to_target(item);
764 ssize_t ret = -EINVAL;
765 int ipv6;
766
767 mutex_lock(&dynamic_netconsole_mutex);
768 if (nt->enabled) {
769 pr_err("target (%s) is enabled, disable to update parameters\n",
770 config_item_name(&nt->group.cg_item));
771 goto out_unlock;
772 }
773
774 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.local_ip);
775 if (ipv6 == -1)
776 goto out_unlock;
777 nt->np.ipv6 = !!ipv6;
778
779 ret = strnlen(buf, count);
780 out_unlock:
781 mutex_unlock(&dynamic_netconsole_mutex);
782 return ret;
783 }
784
remote_ip_store(struct config_item * item,const char * buf,size_t count)785 static ssize_t remote_ip_store(struct config_item *item, const char *buf,
786 size_t count)
787 {
788 struct netconsole_target *nt = to_target(item);
789 ssize_t ret = -EINVAL;
790 int ipv6;
791
792 mutex_lock(&dynamic_netconsole_mutex);
793 if (nt->enabled) {
794 pr_err("target (%s) is enabled, disable to update parameters\n",
795 config_item_name(&nt->group.cg_item));
796 goto out_unlock;
797 }
798
799 ipv6 = netpoll_parse_ip_addr(buf, &nt->np.remote_ip);
800 if (ipv6 == -1)
801 goto out_unlock;
802 nt->np.ipv6 = !!ipv6;
803
804 ret = strnlen(buf, count);
805 out_unlock:
806 mutex_unlock(&dynamic_netconsole_mutex);
807 return ret;
808 }
809
810 /* Count number of entries we have in userdata.
811 * This is important because userdata only supports MAX_USERDATA_ITEMS
812 * entries. Before enabling any new userdata feature, number of entries needs
813 * to checked for available space.
814 */
count_userdata_entries(struct netconsole_target * nt)815 static size_t count_userdata_entries(struct netconsole_target *nt)
816 {
817 return list_count_nodes(&nt->userdata_group.cg_children);
818 }
819
remote_mac_store(struct config_item * item,const char * buf,size_t count)820 static ssize_t remote_mac_store(struct config_item *item, const char *buf,
821 size_t count)
822 {
823 struct netconsole_target *nt = to_target(item);
824 u8 remote_mac[ETH_ALEN];
825 ssize_t ret = -EINVAL;
826
827 mutex_lock(&dynamic_netconsole_mutex);
828 if (nt->enabled) {
829 pr_err("target (%s) is enabled, disable to update parameters\n",
830 config_item_name(&nt->group.cg_item));
831 goto out_unlock;
832 }
833
834 if (!mac_pton(buf, remote_mac))
835 goto out_unlock;
836 if (buf[MAC_ADDR_STR_LEN] && buf[MAC_ADDR_STR_LEN] != '\n')
837 goto out_unlock;
838 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
839
840 ret = strnlen(buf, count);
841 out_unlock:
842 mutex_unlock(&dynamic_netconsole_mutex);
843 return ret;
844 }
845
846 struct userdatum {
847 struct config_item item;
848 char value[MAX_EXTRADATA_VALUE_LEN];
849 };
850
to_userdatum(struct config_item * item)851 static struct userdatum *to_userdatum(struct config_item *item)
852 {
853 return container_of(item, struct userdatum, item);
854 }
855
856 struct userdata {
857 struct config_group group;
858 };
859
to_userdata(struct config_item * item)860 static struct userdata *to_userdata(struct config_item *item)
861 {
862 return container_of(to_config_group(item), struct userdata, group);
863 }
864
userdata_to_target(struct userdata * ud)865 static struct netconsole_target *userdata_to_target(struct userdata *ud)
866 {
867 struct config_group *netconsole_group;
868
869 netconsole_group = to_config_group(ud->group.cg_item.ci_parent);
870 return to_target(&netconsole_group->cg_item);
871 }
872
userdatum_value_show(struct config_item * item,char * buf)873 static ssize_t userdatum_value_show(struct config_item *item, char *buf)
874 {
875 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));
876 }
877
878 /* Navigate configfs and calculate the lentgh of the formatted string
879 * representing userdata.
880 * Must be called holding netconsole_subsys.su_mutex
881 */
calc_userdata_len(struct netconsole_target * nt)882 static int calc_userdata_len(struct netconsole_target *nt)
883 {
884 struct userdatum *udm_item;
885 struct config_item *item;
886 struct list_head *entry;
887 int len = 0;
888
889 list_for_each(entry, &nt->userdata_group.cg_children) {
890 item = container_of(entry, struct config_item, ci_entry);
891 udm_item = to_userdatum(item);
892 /* Skip userdata with no value set */
893 if (udm_item->value[0]) {
894 len += snprintf(NULL, 0, " %s=%s\n", item->ci_name,
895 udm_item->value);
896 }
897 }
898 return len;
899 }
900
update_userdata(struct netconsole_target * nt)901 static int update_userdata(struct netconsole_target *nt)
902 {
903 struct userdatum *udm_item;
904 struct config_item *item;
905 struct list_head *entry;
906 char *old_buf = NULL;
907 char *new_buf = NULL;
908 unsigned long flags;
909 int offset = 0;
910 int len;
911
912 /* Calculate required buffer size */
913 len = calc_userdata_len(nt);
914
915 if (WARN_ON_ONCE(len > MAX_EXTRADATA_ENTRY_LEN * MAX_USERDATA_ITEMS))
916 return -ENOSPC;
917
918 /* Allocate new buffer */
919 if (len) {
920 new_buf = kmalloc(len + 1, GFP_KERNEL);
921 if (!new_buf)
922 return -ENOMEM;
923 }
924
925 /* Write userdata to new buffer */
926 list_for_each(entry, &nt->userdata_group.cg_children) {
927 item = container_of(entry, struct config_item, ci_entry);
928 udm_item = to_userdatum(item);
929 /* Skip userdata with no value set */
930 if (udm_item->value[0]) {
931 offset += scnprintf(&new_buf[offset], len + 1 - offset,
932 " %s=%s\n", item->ci_name,
933 udm_item->value);
934 }
935 }
936
937 WARN_ON_ONCE(offset != len);
938
939 /* Switch to new buffer and free old buffer */
940 spin_lock_irqsave(&target_list_lock, flags);
941 old_buf = nt->userdata;
942 nt->userdata = new_buf;
943 nt->userdata_length = offset;
944 spin_unlock_irqrestore(&target_list_lock, flags);
945
946 kfree(old_buf);
947
948 return 0;
949 }
950
userdatum_value_store(struct config_item * item,const char * buf,size_t count)951 static ssize_t userdatum_value_store(struct config_item *item, const char *buf,
952 size_t count)
953 {
954 struct userdatum *udm = to_userdatum(item);
955 struct netconsole_target *nt;
956 struct userdata *ud;
957 ssize_t ret;
958
959 if (count > MAX_EXTRADATA_VALUE_LEN)
960 return -EMSGSIZE;
961
962 mutex_lock(&netconsole_subsys.su_mutex);
963 mutex_lock(&dynamic_netconsole_mutex);
964
965 ret = strscpy(udm->value, buf, sizeof(udm->value));
966 if (ret < 0)
967 goto out_unlock;
968 trim_newline(udm->value, sizeof(udm->value));
969
970 ud = to_userdata(item->ci_parent);
971 nt = userdata_to_target(ud);
972 ret = update_userdata(nt);
973 if (ret < 0)
974 goto out_unlock;
975 ret = count;
976 out_unlock:
977 mutex_unlock(&dynamic_netconsole_mutex);
978 mutex_unlock(&netconsole_subsys.su_mutex);
979 return ret;
980 }
981
982 /* disable_sysdata_feature - Disable sysdata feature and clean sysdata
983 * @nt: target that is disabling the feature
984 * @feature: feature being disabled
985 */
disable_sysdata_feature(struct netconsole_target * nt,enum sysdata_feature feature)986 static void disable_sysdata_feature(struct netconsole_target *nt,
987 enum sysdata_feature feature)
988 {
989 nt->sysdata_fields &= ~feature;
990 nt->sysdata[0] = 0;
991 }
992
sysdata_msgid_enabled_store(struct config_item * item,const char * buf,size_t count)993 static ssize_t sysdata_msgid_enabled_store(struct config_item *item,
994 const char *buf, size_t count)
995 {
996 struct netconsole_target *nt = to_target(item->ci_parent);
997 bool msgid_enabled, curr;
998 ssize_t ret;
999
1000 ret = kstrtobool(buf, &msgid_enabled);
1001 if (ret)
1002 return ret;
1003
1004 mutex_lock(&netconsole_subsys.su_mutex);
1005 mutex_lock(&dynamic_netconsole_mutex);
1006 curr = !!(nt->sysdata_fields & SYSDATA_MSGID);
1007 if (msgid_enabled == curr)
1008 goto unlock_ok;
1009
1010 if (msgid_enabled)
1011 nt->sysdata_fields |= SYSDATA_MSGID;
1012 else
1013 disable_sysdata_feature(nt, SYSDATA_MSGID);
1014
1015 unlock_ok:
1016 ret = strnlen(buf, count);
1017 mutex_unlock(&dynamic_netconsole_mutex);
1018 mutex_unlock(&netconsole_subsys.su_mutex);
1019 return ret;
1020 }
1021
sysdata_release_enabled_store(struct config_item * item,const char * buf,size_t count)1022 static ssize_t sysdata_release_enabled_store(struct config_item *item,
1023 const char *buf, size_t count)
1024 {
1025 struct netconsole_target *nt = to_target(item->ci_parent);
1026 bool release_enabled, curr;
1027 ssize_t ret;
1028
1029 ret = kstrtobool(buf, &release_enabled);
1030 if (ret)
1031 return ret;
1032
1033 mutex_lock(&netconsole_subsys.su_mutex);
1034 mutex_lock(&dynamic_netconsole_mutex);
1035 curr = !!(nt->sysdata_fields & SYSDATA_RELEASE);
1036 if (release_enabled == curr)
1037 goto unlock_ok;
1038
1039 if (release_enabled)
1040 nt->sysdata_fields |= SYSDATA_RELEASE;
1041 else
1042 disable_sysdata_feature(nt, SYSDATA_RELEASE);
1043
1044 unlock_ok:
1045 ret = strnlen(buf, count);
1046 mutex_unlock(&dynamic_netconsole_mutex);
1047 mutex_unlock(&netconsole_subsys.su_mutex);
1048 return ret;
1049 }
1050
sysdata_taskname_enabled_store(struct config_item * item,const char * buf,size_t count)1051 static ssize_t sysdata_taskname_enabled_store(struct config_item *item,
1052 const char *buf, size_t count)
1053 {
1054 struct netconsole_target *nt = to_target(item->ci_parent);
1055 bool taskname_enabled, curr;
1056 ssize_t ret;
1057
1058 ret = kstrtobool(buf, &taskname_enabled);
1059 if (ret)
1060 return ret;
1061
1062 mutex_lock(&netconsole_subsys.su_mutex);
1063 mutex_lock(&dynamic_netconsole_mutex);
1064 curr = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
1065 if (taskname_enabled == curr)
1066 goto unlock_ok;
1067
1068 if (taskname_enabled)
1069 nt->sysdata_fields |= SYSDATA_TASKNAME;
1070 else
1071 disable_sysdata_feature(nt, SYSDATA_TASKNAME);
1072
1073 unlock_ok:
1074 ret = strnlen(buf, count);
1075 mutex_unlock(&dynamic_netconsole_mutex);
1076 mutex_unlock(&netconsole_subsys.su_mutex);
1077 return ret;
1078 }
1079
1080 /* configfs helper to sysdata cpu_nr feature */
sysdata_cpu_nr_enabled_store(struct config_item * item,const char * buf,size_t count)1081 static ssize_t sysdata_cpu_nr_enabled_store(struct config_item *item,
1082 const char *buf, size_t count)
1083 {
1084 struct netconsole_target *nt = to_target(item->ci_parent);
1085 bool cpu_nr_enabled, curr;
1086 ssize_t ret;
1087
1088 ret = kstrtobool(buf, &cpu_nr_enabled);
1089 if (ret)
1090 return ret;
1091
1092 mutex_lock(&netconsole_subsys.su_mutex);
1093 mutex_lock(&dynamic_netconsole_mutex);
1094 curr = !!(nt->sysdata_fields & SYSDATA_CPU_NR);
1095 if (cpu_nr_enabled == curr)
1096 /* no change requested */
1097 goto unlock_ok;
1098
1099 if (cpu_nr_enabled)
1100 nt->sysdata_fields |= SYSDATA_CPU_NR;
1101 else
1102 /* This is special because sysdata might have remaining data
1103 * from previous sysdata, and it needs to be cleaned.
1104 */
1105 disable_sysdata_feature(nt, SYSDATA_CPU_NR);
1106
1107 unlock_ok:
1108 ret = strnlen(buf, count);
1109 mutex_unlock(&dynamic_netconsole_mutex);
1110 mutex_unlock(&netconsole_subsys.su_mutex);
1111 return ret;
1112 }
1113
1114 CONFIGFS_ATTR(userdatum_, value);
1115 CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
1116 CONFIGFS_ATTR(sysdata_, taskname_enabled);
1117 CONFIGFS_ATTR(sysdata_, release_enabled);
1118 CONFIGFS_ATTR(sysdata_, msgid_enabled);
1119
1120 static struct configfs_attribute *userdatum_attrs[] = {
1121 &userdatum_attr_value,
1122 NULL,
1123 };
1124
userdatum_release(struct config_item * item)1125 static void userdatum_release(struct config_item *item)
1126 {
1127 kfree(to_userdatum(item));
1128 }
1129
1130 static struct configfs_item_operations userdatum_ops = {
1131 .release = userdatum_release,
1132 };
1133
1134 static const struct config_item_type userdatum_type = {
1135 .ct_item_ops = &userdatum_ops,
1136 .ct_attrs = userdatum_attrs,
1137 .ct_owner = THIS_MODULE,
1138 };
1139
userdatum_make_item(struct config_group * group,const char * name)1140 static struct config_item *userdatum_make_item(struct config_group *group,
1141 const char *name)
1142 {
1143 struct netconsole_target *nt;
1144 struct userdatum *udm;
1145 struct userdata *ud;
1146
1147 if (strlen(name) > MAX_EXTRADATA_NAME_LEN)
1148 return ERR_PTR(-ENAMETOOLONG);
1149
1150 ud = to_userdata(&group->cg_item);
1151 nt = userdata_to_target(ud);
1152 if (count_userdata_entries(nt) >= MAX_USERDATA_ITEMS)
1153 return ERR_PTR(-ENOSPC);
1154
1155 udm = kzalloc(sizeof(*udm), GFP_KERNEL);
1156 if (!udm)
1157 return ERR_PTR(-ENOMEM);
1158
1159 config_item_init_type_name(&udm->item, name, &userdatum_type);
1160 return &udm->item;
1161 }
1162
userdatum_drop(struct config_group * group,struct config_item * item)1163 static void userdatum_drop(struct config_group *group, struct config_item *item)
1164 {
1165 struct netconsole_target *nt;
1166 struct userdata *ud;
1167
1168 ud = to_userdata(&group->cg_item);
1169 nt = userdata_to_target(ud);
1170
1171 mutex_lock(&dynamic_netconsole_mutex);
1172 update_userdata(nt);
1173 config_item_put(item);
1174 mutex_unlock(&dynamic_netconsole_mutex);
1175 }
1176
1177 static struct configfs_attribute *userdata_attrs[] = {
1178 &sysdata_attr_cpu_nr_enabled,
1179 &sysdata_attr_taskname_enabled,
1180 &sysdata_attr_release_enabled,
1181 &sysdata_attr_msgid_enabled,
1182 NULL,
1183 };
1184
1185 static struct configfs_group_operations userdata_ops = {
1186 .make_item = userdatum_make_item,
1187 .drop_item = userdatum_drop,
1188 };
1189
1190 static const struct config_item_type userdata_type = {
1191 .ct_item_ops = &userdatum_ops,
1192 .ct_group_ops = &userdata_ops,
1193 .ct_attrs = userdata_attrs,
1194 .ct_owner = THIS_MODULE,
1195 };
1196
1197 CONFIGFS_ATTR(, enabled);
1198 CONFIGFS_ATTR(, extended);
1199 CONFIGFS_ATTR(, dev_name);
1200 CONFIGFS_ATTR(, local_port);
1201 CONFIGFS_ATTR(, remote_port);
1202 CONFIGFS_ATTR(, local_ip);
1203 CONFIGFS_ATTR(, remote_ip);
1204 CONFIGFS_ATTR_RO(, local_mac);
1205 CONFIGFS_ATTR(, remote_mac);
1206 CONFIGFS_ATTR(, release);
1207 CONFIGFS_ATTR_RO(, transmit_errors);
1208
1209 static struct configfs_attribute *netconsole_target_attrs[] = {
1210 &attr_enabled,
1211 &attr_extended,
1212 &attr_release,
1213 &attr_dev_name,
1214 &attr_local_port,
1215 &attr_remote_port,
1216 &attr_local_ip,
1217 &attr_remote_ip,
1218 &attr_local_mac,
1219 &attr_remote_mac,
1220 &attr_transmit_errors,
1221 NULL,
1222 };
1223
1224 /*
1225 * Item operations and type for netconsole_target.
1226 */
1227
netconsole_target_release(struct config_item * item)1228 static void netconsole_target_release(struct config_item *item)
1229 {
1230 struct netconsole_target *nt = to_target(item);
1231
1232 kfree(nt->userdata);
1233 kfree(nt);
1234 }
1235
1236 static struct configfs_item_operations netconsole_target_item_ops = {
1237 .release = netconsole_target_release,
1238 };
1239
1240 static const struct config_item_type netconsole_target_type = {
1241 .ct_attrs = netconsole_target_attrs,
1242 .ct_item_ops = &netconsole_target_item_ops,
1243 .ct_owner = THIS_MODULE,
1244 };
1245
init_target_config_group(struct netconsole_target * nt,const char * name)1246 static void init_target_config_group(struct netconsole_target *nt,
1247 const char *name)
1248 {
1249 config_group_init_type_name(&nt->group, name, &netconsole_target_type);
1250 config_group_init_type_name(&nt->userdata_group, "userdata",
1251 &userdata_type);
1252 configfs_add_default_group(&nt->userdata_group, &nt->group);
1253 }
1254
find_cmdline_target(const char * name)1255 static struct netconsole_target *find_cmdline_target(const char *name)
1256 {
1257 struct netconsole_target *nt, *ret = NULL;
1258 unsigned long flags;
1259
1260 spin_lock_irqsave(&target_list_lock, flags);
1261 list_for_each_entry(nt, &target_list, list) {
1262 if (!strcmp(nt->group.cg_item.ci_name, name)) {
1263 ret = nt;
1264 break;
1265 }
1266 }
1267 spin_unlock_irqrestore(&target_list_lock, flags);
1268
1269 return ret;
1270 }
1271
1272 /*
1273 * Group operations and type for netconsole_subsys.
1274 */
1275
make_netconsole_target(struct config_group * group,const char * name)1276 static struct config_group *make_netconsole_target(struct config_group *group,
1277 const char *name)
1278 {
1279 struct netconsole_target *nt;
1280 unsigned long flags;
1281
1282 /* Checking if a target by this name was created at boot time. If so,
1283 * attach a configfs entry to that target. This enables dynamic
1284 * control.
1285 */
1286 if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
1287 strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
1288 nt = find_cmdline_target(name);
1289 if (nt) {
1290 init_target_config_group(nt, name);
1291 return &nt->group;
1292 }
1293 }
1294
1295 nt = alloc_and_init();
1296 if (!nt)
1297 return ERR_PTR(-ENOMEM);
1298
1299 /* Initialize the config_group member */
1300 init_target_config_group(nt, name);
1301
1302 /* Adding, but it is disabled */
1303 spin_lock_irqsave(&target_list_lock, flags);
1304 list_add(&nt->list, &target_list);
1305 spin_unlock_irqrestore(&target_list_lock, flags);
1306
1307 return &nt->group;
1308 }
1309
drop_netconsole_target(struct config_group * group,struct config_item * item)1310 static void drop_netconsole_target(struct config_group *group,
1311 struct config_item *item)
1312 {
1313 unsigned long flags;
1314 struct netconsole_target *nt = to_target(item);
1315
1316 spin_lock_irqsave(&target_list_lock, flags);
1317 list_del(&nt->list);
1318 spin_unlock_irqrestore(&target_list_lock, flags);
1319
1320 /*
1321 * The target may have never been enabled, or was manually disabled
1322 * before being removed so netpoll may have already been cleaned up.
1323 */
1324 if (nt->enabled)
1325 netpoll_cleanup(&nt->np);
1326
1327 config_item_put(&nt->group.cg_item);
1328 }
1329
1330 static struct configfs_group_operations netconsole_subsys_group_ops = {
1331 .make_group = make_netconsole_target,
1332 .drop_item = drop_netconsole_target,
1333 };
1334
1335 static const struct config_item_type netconsole_subsys_type = {
1336 .ct_group_ops = &netconsole_subsys_group_ops,
1337 .ct_owner = THIS_MODULE,
1338 };
1339
1340 /* The netconsole configfs subsystem */
1341 static struct configfs_subsystem netconsole_subsys = {
1342 .su_group = {
1343 .cg_item = {
1344 .ci_namebuf = "netconsole",
1345 .ci_type = &netconsole_subsys_type,
1346 },
1347 },
1348 };
1349
populate_configfs_item(struct netconsole_target * nt,int cmdline_count)1350 static void populate_configfs_item(struct netconsole_target *nt,
1351 int cmdline_count)
1352 {
1353 char target_name[16];
1354
1355 snprintf(target_name, sizeof(target_name), "%s%d",
1356 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1357 init_target_config_group(nt, target_name);
1358 }
1359
sysdata_append_cpu_nr(struct netconsole_target * nt,int offset)1360 static int sysdata_append_cpu_nr(struct netconsole_target *nt, int offset)
1361 {
1362 return scnprintf(&nt->sysdata[offset],
1363 MAX_EXTRADATA_ENTRY_LEN, " cpu=%u\n",
1364 raw_smp_processor_id());
1365 }
1366
sysdata_append_taskname(struct netconsole_target * nt,int offset)1367 static int sysdata_append_taskname(struct netconsole_target *nt, int offset)
1368 {
1369 return scnprintf(&nt->sysdata[offset],
1370 MAX_EXTRADATA_ENTRY_LEN, " taskname=%s\n",
1371 current->comm);
1372 }
1373
sysdata_append_release(struct netconsole_target * nt,int offset)1374 static int sysdata_append_release(struct netconsole_target *nt, int offset)
1375 {
1376 return scnprintf(&nt->sysdata[offset],
1377 MAX_EXTRADATA_ENTRY_LEN, " release=%s\n",
1378 init_utsname()->release);
1379 }
1380
sysdata_append_msgid(struct netconsole_target * nt,int offset)1381 static int sysdata_append_msgid(struct netconsole_target *nt, int offset)
1382 {
1383 wrapping_assign_add(nt->msgcounter, 1);
1384 return scnprintf(&nt->sysdata[offset],
1385 MAX_EXTRADATA_ENTRY_LEN, " msgid=%u\n",
1386 nt->msgcounter);
1387 }
1388
1389 /*
1390 * prepare_sysdata - append sysdata in runtime
1391 * @nt: target to send message to
1392 */
prepare_sysdata(struct netconsole_target * nt)1393 static int prepare_sysdata(struct netconsole_target *nt)
1394 {
1395 int sysdata_len = 0;
1396
1397 if (!nt->sysdata_fields)
1398 goto out;
1399
1400 if (nt->sysdata_fields & SYSDATA_CPU_NR)
1401 sysdata_len += sysdata_append_cpu_nr(nt, sysdata_len);
1402 if (nt->sysdata_fields & SYSDATA_TASKNAME)
1403 sysdata_len += sysdata_append_taskname(nt, sysdata_len);
1404 if (nt->sysdata_fields & SYSDATA_RELEASE)
1405 sysdata_len += sysdata_append_release(nt, sysdata_len);
1406 if (nt->sysdata_fields & SYSDATA_MSGID)
1407 sysdata_len += sysdata_append_msgid(nt, sysdata_len);
1408
1409 WARN_ON_ONCE(sysdata_len >
1410 MAX_EXTRADATA_ENTRY_LEN * MAX_SYSDATA_ITEMS);
1411
1412 out:
1413 return sysdata_len;
1414 }
1415 #endif /* CONFIG_NETCONSOLE_DYNAMIC */
1416
1417 /* Handle network interface device notifications */
netconsole_netdev_event(struct notifier_block * this,unsigned long event,void * ptr)1418 static int netconsole_netdev_event(struct notifier_block *this,
1419 unsigned long event, void *ptr)
1420 {
1421 unsigned long flags;
1422 struct netconsole_target *nt, *tmp;
1423 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1424 bool stopped = false;
1425
1426 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
1427 event == NETDEV_RELEASE || event == NETDEV_JOIN))
1428 goto done;
1429
1430 mutex_lock(&target_cleanup_list_lock);
1431 spin_lock_irqsave(&target_list_lock, flags);
1432 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1433 netconsole_target_get(nt);
1434 if (nt->np.dev == dev) {
1435 switch (event) {
1436 case NETDEV_CHANGENAME:
1437 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
1438 break;
1439 case NETDEV_RELEASE:
1440 case NETDEV_JOIN:
1441 case NETDEV_UNREGISTER:
1442 nt->enabled = false;
1443 list_move(&nt->list, &target_cleanup_list);
1444 stopped = true;
1445 }
1446 }
1447 netconsole_target_put(nt);
1448 }
1449 spin_unlock_irqrestore(&target_list_lock, flags);
1450 mutex_unlock(&target_cleanup_list_lock);
1451
1452 if (stopped) {
1453 const char *msg = "had an event";
1454
1455 switch (event) {
1456 case NETDEV_UNREGISTER:
1457 msg = "unregistered";
1458 break;
1459 case NETDEV_RELEASE:
1460 msg = "released slaves";
1461 break;
1462 case NETDEV_JOIN:
1463 msg = "is joining a master device";
1464 break;
1465 }
1466 pr_info("network logging stopped on interface %s as it %s\n",
1467 dev->name, msg);
1468 }
1469
1470 /* Process target_cleanup_list entries. By the end, target_cleanup_list
1471 * should be empty
1472 */
1473 netconsole_process_cleanups_core();
1474
1475 done:
1476 return NOTIFY_DONE;
1477 }
1478
1479 static struct notifier_block netconsole_netdev_notifier = {
1480 .notifier_call = netconsole_netdev_event,
1481 };
1482
1483 /**
1484 * send_udp - Wrapper for netpoll_send_udp that counts errors
1485 * @nt: target to send message to
1486 * @msg: message to send
1487 * @len: length of message
1488 *
1489 * Calls netpoll_send_udp and classifies the return value. If an error
1490 * occurred it increments statistics in nt->stats accordingly.
1491 * Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
1492 */
send_udp(struct netconsole_target * nt,const char * msg,int len)1493 static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1494 {
1495 int result = netpoll_send_udp(&nt->np, msg, len);
1496
1497 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1498 if (result == NET_XMIT_DROP) {
1499 u64_stats_update_begin(&nt->stats.syncp);
1500 u64_stats_inc(&nt->stats.xmit_drop_count);
1501 u64_stats_update_end(&nt->stats.syncp);
1502 } else if (result == -ENOMEM) {
1503 u64_stats_update_begin(&nt->stats.syncp);
1504 u64_stats_inc(&nt->stats.enomem_count);
1505 u64_stats_update_end(&nt->stats.syncp);
1506 }
1507 }
1508 }
1509
send_msg_no_fragmentation(struct netconsole_target * nt,const char * msg,int msg_len,int release_len)1510 static void send_msg_no_fragmentation(struct netconsole_target *nt,
1511 const char *msg,
1512 int msg_len,
1513 int release_len)
1514 {
1515 const char *userdata = NULL;
1516 const char *sysdata = NULL;
1517 const char *release;
1518
1519 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1520 userdata = nt->userdata;
1521 sysdata = nt->sysdata;
1522 #endif
1523
1524 if (release_len) {
1525 release = init_utsname()->release;
1526
1527 scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
1528 msg_len += release_len;
1529 } else {
1530 memcpy(nt->buf, msg, msg_len);
1531 }
1532
1533 if (userdata)
1534 msg_len += scnprintf(&nt->buf[msg_len],
1535 MAX_PRINT_CHUNK - msg_len, "%s",
1536 userdata);
1537
1538 if (sysdata)
1539 msg_len += scnprintf(&nt->buf[msg_len],
1540 MAX_PRINT_CHUNK - msg_len, "%s",
1541 sysdata);
1542
1543 send_udp(nt, nt->buf, msg_len);
1544 }
1545
append_release(char * buf)1546 static void append_release(char *buf)
1547 {
1548 const char *release;
1549
1550 release = init_utsname()->release;
1551 scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
1552 }
1553
send_fragmented_body(struct netconsole_target * nt,const char * msgbody_ptr,int header_len,int msgbody_len,int sysdata_len)1554 static void send_fragmented_body(struct netconsole_target *nt,
1555 const char *msgbody_ptr, int header_len,
1556 int msgbody_len, int sysdata_len)
1557 {
1558 const char *userdata_ptr = NULL;
1559 const char *sysdata_ptr = NULL;
1560 int data_len, data_sent = 0;
1561 int userdata_offset = 0;
1562 int sysdata_offset = 0;
1563 int msgbody_offset = 0;
1564 int userdata_len = 0;
1565
1566 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1567 userdata_ptr = nt->userdata;
1568 sysdata_ptr = nt->sysdata;
1569 userdata_len = nt->userdata_length;
1570 #endif
1571 if (WARN_ON_ONCE(!userdata_ptr && userdata_len != 0))
1572 return;
1573
1574 if (WARN_ON_ONCE(!sysdata_ptr && sysdata_len != 0))
1575 return;
1576
1577 /* data_len represents the number of bytes that will be sent. This is
1578 * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
1579 * packets
1580 */
1581 data_len = msgbody_len + userdata_len + sysdata_len;
1582
1583 /* In each iteration of the while loop below, we send a packet
1584 * containing the header and a portion of the data. The data is
1585 * composed of three parts: msgbody, userdata, and sysdata.
1586 * We keep track of how many bytes have been sent from each part using
1587 * the *_offset variables.
1588 * We keep track of how many bytes have been sent overall using the
1589 * data_sent variable, which ranges from 0 to the total bytes to be
1590 * sent.
1591 */
1592 while (data_sent < data_len) {
1593 int userdata_left = userdata_len - userdata_offset;
1594 int sysdata_left = sysdata_len - sysdata_offset;
1595 int msgbody_left = msgbody_len - msgbody_offset;
1596 int buf_offset = 0;
1597 int this_chunk = 0;
1598
1599 /* header is already populated in nt->buf, just append to it */
1600 buf_offset = header_len;
1601
1602 buf_offset += scnprintf(nt->buf + buf_offset,
1603 MAX_PRINT_CHUNK - buf_offset,
1604 ",ncfrag=%d/%d;", data_sent,
1605 data_len);
1606
1607 /* append msgbody first */
1608 this_chunk = min(msgbody_left, MAX_PRINT_CHUNK - buf_offset);
1609 memcpy(nt->buf + buf_offset, msgbody_ptr + msgbody_offset,
1610 this_chunk);
1611 msgbody_offset += this_chunk;
1612 buf_offset += this_chunk;
1613 data_sent += this_chunk;
1614
1615 /* after msgbody, append userdata */
1616 if (userdata_ptr && userdata_left) {
1617 this_chunk = min(userdata_left,
1618 MAX_PRINT_CHUNK - buf_offset);
1619 memcpy(nt->buf + buf_offset,
1620 userdata_ptr + userdata_offset, this_chunk);
1621 userdata_offset += this_chunk;
1622 buf_offset += this_chunk;
1623 data_sent += this_chunk;
1624 }
1625
1626 /* after userdata, append sysdata */
1627 if (sysdata_ptr && sysdata_left) {
1628 this_chunk = min(sysdata_left,
1629 MAX_PRINT_CHUNK - buf_offset);
1630 memcpy(nt->buf + buf_offset,
1631 sysdata_ptr + sysdata_offset, this_chunk);
1632 sysdata_offset += this_chunk;
1633 buf_offset += this_chunk;
1634 data_sent += this_chunk;
1635 }
1636
1637 /* if all is good, send the packet out */
1638 if (WARN_ON_ONCE(data_sent > data_len))
1639 return;
1640
1641 send_udp(nt, nt->buf, buf_offset);
1642 }
1643 }
1644
send_msg_fragmented(struct netconsole_target * nt,const char * msg,int msg_len,int release_len,int sysdata_len)1645 static void send_msg_fragmented(struct netconsole_target *nt,
1646 const char *msg,
1647 int msg_len,
1648 int release_len,
1649 int sysdata_len)
1650 {
1651 int header_len, msgbody_len;
1652 const char *msgbody;
1653
1654 /* need to insert extra header fields, detect header and msgbody */
1655 msgbody = memchr(msg, ';', msg_len);
1656 if (WARN_ON_ONCE(!msgbody))
1657 return;
1658
1659 header_len = msgbody - msg;
1660 msgbody_len = msg_len - header_len - 1;
1661 msgbody++;
1662
1663 /*
1664 * Transfer multiple chunks with the following extra header.
1665 * "ncfrag=<byte-offset>/<total-bytes>"
1666 */
1667 if (release_len)
1668 append_release(nt->buf);
1669
1670 /* Copy the header into the buffer */
1671 memcpy(nt->buf + release_len, msg, header_len);
1672 header_len += release_len;
1673
1674 /* for now on, the header will be persisted, and the msgbody
1675 * will be replaced
1676 */
1677 send_fragmented_body(nt, msgbody, header_len, msgbody_len,
1678 sysdata_len);
1679 }
1680
1681 /**
1682 * send_ext_msg_udp - send extended log message to target
1683 * @nt: target to send message to
1684 * @msg: extended log message to send
1685 * @msg_len: length of message
1686 *
1687 * Transfer extended log @msg to @nt. If @msg is longer than
1688 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
1689 * ncfrag header field added to identify them.
1690 */
send_ext_msg_udp(struct netconsole_target * nt,const char * msg,int msg_len)1691 static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
1692 int msg_len)
1693 {
1694 int userdata_len = 0;
1695 int release_len = 0;
1696 int sysdata_len = 0;
1697
1698 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1699 sysdata_len = prepare_sysdata(nt);
1700 userdata_len = nt->userdata_length;
1701 #endif
1702 if (nt->release)
1703 release_len = strlen(init_utsname()->release) + 1;
1704
1705 if (msg_len + release_len + sysdata_len + userdata_len <= MAX_PRINT_CHUNK)
1706 return send_msg_no_fragmentation(nt, msg, msg_len, release_len);
1707
1708 return send_msg_fragmented(nt, msg, msg_len, release_len,
1709 sysdata_len);
1710 }
1711
write_ext_msg(struct console * con,const char * msg,unsigned int len)1712 static void write_ext_msg(struct console *con, const char *msg,
1713 unsigned int len)
1714 {
1715 struct netconsole_target *nt;
1716 unsigned long flags;
1717
1718 if ((oops_only && !oops_in_progress) || list_empty(&target_list))
1719 return;
1720
1721 spin_lock_irqsave(&target_list_lock, flags);
1722 list_for_each_entry(nt, &target_list, list)
1723 if (nt->extended && nt->enabled && netif_running(nt->np.dev))
1724 send_ext_msg_udp(nt, msg, len);
1725 spin_unlock_irqrestore(&target_list_lock, flags);
1726 }
1727
write_msg(struct console * con,const char * msg,unsigned int len)1728 static void write_msg(struct console *con, const char *msg, unsigned int len)
1729 {
1730 int frag, left;
1731 unsigned long flags;
1732 struct netconsole_target *nt;
1733 const char *tmp;
1734
1735 if (oops_only && !oops_in_progress)
1736 return;
1737 /* Avoid taking lock and disabling interrupts unnecessarily */
1738 if (list_empty(&target_list))
1739 return;
1740
1741 spin_lock_irqsave(&target_list_lock, flags);
1742 list_for_each_entry(nt, &target_list, list) {
1743 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {
1744 /*
1745 * We nest this inside the for-each-target loop above
1746 * so that we're able to get as much logging out to
1747 * at least one target if we die inside here, instead
1748 * of unnecessarily keeping all targets in lock-step.
1749 */
1750 tmp = msg;
1751 for (left = len; left;) {
1752 frag = min(left, MAX_PRINT_CHUNK);
1753 send_udp(nt, tmp, frag);
1754 tmp += frag;
1755 left -= frag;
1756 }
1757 }
1758 }
1759 spin_unlock_irqrestore(&target_list_lock, flags);
1760 }
1761
netconsole_parser_cmdline(struct netpoll * np,char * opt)1762 static int netconsole_parser_cmdline(struct netpoll *np, char *opt)
1763 {
1764 bool ipversion_set = false;
1765 char *cur = opt;
1766 char *delim;
1767 int ipv6;
1768
1769 if (*cur != '@') {
1770 delim = strchr(cur, '@');
1771 if (!delim)
1772 goto parse_failed;
1773 *delim = 0;
1774 if (kstrtou16(cur, 10, &np->local_port))
1775 goto parse_failed;
1776 cur = delim;
1777 }
1778 cur++;
1779
1780 if (*cur != '/') {
1781 ipversion_set = true;
1782 delim = strchr(cur, '/');
1783 if (!delim)
1784 goto parse_failed;
1785 *delim = 0;
1786 ipv6 = netpoll_parse_ip_addr(cur, &np->local_ip);
1787 if (ipv6 < 0)
1788 goto parse_failed;
1789 else
1790 np->ipv6 = (bool)ipv6;
1791 cur = delim;
1792 }
1793 cur++;
1794
1795 if (*cur != ',') {
1796 /* parse out dev_name or dev_mac */
1797 delim = strchr(cur, ',');
1798 if (!delim)
1799 goto parse_failed;
1800 *delim = 0;
1801
1802 np->dev_name[0] = '\0';
1803 eth_broadcast_addr(np->dev_mac);
1804 if (!strchr(cur, ':'))
1805 strscpy(np->dev_name, cur, sizeof(np->dev_name));
1806 else if (!mac_pton(cur, np->dev_mac))
1807 goto parse_failed;
1808
1809 cur = delim;
1810 }
1811 cur++;
1812
1813 if (*cur != '@') {
1814 /* dst port */
1815 delim = strchr(cur, '@');
1816 if (!delim)
1817 goto parse_failed;
1818 *delim = 0;
1819 if (*cur == ' ' || *cur == '\t')
1820 np_info(np, "warning: whitespace is not allowed\n");
1821 if (kstrtou16(cur, 10, &np->remote_port))
1822 goto parse_failed;
1823 cur = delim;
1824 }
1825 cur++;
1826
1827 /* dst ip */
1828 delim = strchr(cur, '/');
1829 if (!delim)
1830 goto parse_failed;
1831 *delim = 0;
1832 ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
1833 if (ipv6 < 0)
1834 goto parse_failed;
1835 else if (ipversion_set && np->ipv6 != (bool)ipv6)
1836 goto parse_failed;
1837 else
1838 np->ipv6 = (bool)ipv6;
1839 cur = delim + 1;
1840
1841 if (*cur != 0) {
1842 /* MAC address */
1843 if (!mac_pton(cur, np->remote_mac))
1844 goto parse_failed;
1845 }
1846
1847 netconsole_print_banner(np);
1848
1849 return 0;
1850
1851 parse_failed:
1852 np_info(np, "couldn't parse config at '%s'!\n", cur);
1853 return -1;
1854 }
1855
1856 /* Allocate new target (from boot/module param) and setup netpoll for it */
alloc_param_target(char * target_config,int cmdline_count)1857 static struct netconsole_target *alloc_param_target(char *target_config,
1858 int cmdline_count)
1859 {
1860 struct netconsole_target *nt;
1861 int err;
1862
1863 nt = alloc_and_init();
1864 if (!nt) {
1865 err = -ENOMEM;
1866 goto fail;
1867 }
1868
1869 if (*target_config == '+') {
1870 nt->extended = true;
1871 target_config++;
1872 }
1873
1874 if (*target_config == 'r') {
1875 if (!nt->extended) {
1876 pr_err("Netconsole configuration error. Release feature requires extended log message");
1877 err = -EINVAL;
1878 goto fail;
1879 }
1880 nt->release = true;
1881 target_config++;
1882 }
1883
1884 /* Parse parameters and setup netpoll */
1885 err = netconsole_parser_cmdline(&nt->np, target_config);
1886 if (err)
1887 goto fail;
1888
1889 err = netpoll_setup(&nt->np);
1890 if (err) {
1891 pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
1892 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1893 if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1894 /* only fail if dynamic reconfiguration is set,
1895 * otherwise, keep the target in the list, but disabled.
1896 */
1897 goto fail;
1898 } else {
1899 nt->enabled = true;
1900 }
1901 populate_configfs_item(nt, cmdline_count);
1902
1903 return nt;
1904
1905 fail:
1906 kfree(nt);
1907 return ERR_PTR(err);
1908 }
1909
1910 /* Cleanup netpoll for given target (from boot/module param) and free it */
free_param_target(struct netconsole_target * nt)1911 static void free_param_target(struct netconsole_target *nt)
1912 {
1913 netpoll_cleanup(&nt->np);
1914 #ifdef CONFIG_NETCONSOLE_DYNAMIC
1915 kfree(nt->userdata);
1916 #endif
1917 kfree(nt);
1918 }
1919
1920 static struct console netconsole_ext = {
1921 .name = "netcon_ext",
1922 .flags = CON_ENABLED | CON_EXTENDED,
1923 .write = write_ext_msg,
1924 };
1925
1926 static struct console netconsole = {
1927 .name = "netcon",
1928 .flags = CON_ENABLED,
1929 .write = write_msg,
1930 };
1931
init_netconsole(void)1932 static int __init init_netconsole(void)
1933 {
1934 int err;
1935 struct netconsole_target *nt, *tmp;
1936 u32 console_type_needed = 0;
1937 unsigned int count = 0;
1938 unsigned long flags;
1939 char *target_config;
1940 char *input = config;
1941
1942 if (strnlen(input, MAX_PARAM_LENGTH)) {
1943 while ((target_config = strsep(&input, ";"))) {
1944 nt = alloc_param_target(target_config, count);
1945 if (IS_ERR(nt)) {
1946 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1947 continue;
1948 err = PTR_ERR(nt);
1949 goto fail;
1950 }
1951 /* Dump existing printks when we register */
1952 if (nt->extended) {
1953 console_type_needed |= CONS_EXTENDED;
1954 netconsole_ext.flags |= CON_PRINTBUFFER;
1955 } else {
1956 console_type_needed |= CONS_BASIC;
1957 netconsole.flags |= CON_PRINTBUFFER;
1958 }
1959
1960 spin_lock_irqsave(&target_list_lock, flags);
1961 list_add(&nt->list, &target_list);
1962 spin_unlock_irqrestore(&target_list_lock, flags);
1963 count++;
1964 }
1965 }
1966
1967 err = register_netdevice_notifier(&netconsole_netdev_notifier);
1968 if (err)
1969 goto fail;
1970
1971 err = dynamic_netconsole_init();
1972 if (err)
1973 goto undonotifier;
1974
1975 if (console_type_needed & CONS_EXTENDED)
1976 register_console(&netconsole_ext);
1977 if (console_type_needed & CONS_BASIC)
1978 register_console(&netconsole);
1979 pr_info("network logging started\n");
1980
1981 return err;
1982
1983 undonotifier:
1984 unregister_netdevice_notifier(&netconsole_netdev_notifier);
1985
1986 fail:
1987 pr_err("cleaning up\n");
1988
1989 /*
1990 * Remove all targets and destroy them (only targets created
1991 * from the boot/module option exist here). Skipping the list
1992 * lock is safe here, and netpoll_cleanup() will sleep.
1993 */
1994 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1995 list_del(&nt->list);
1996 free_param_target(nt);
1997 }
1998
1999 return err;
2000 }
2001
cleanup_netconsole(void)2002 static void __exit cleanup_netconsole(void)
2003 {
2004 struct netconsole_target *nt, *tmp;
2005
2006 if (console_is_registered(&netconsole_ext))
2007 unregister_console(&netconsole_ext);
2008 if (console_is_registered(&netconsole))
2009 unregister_console(&netconsole);
2010 dynamic_netconsole_exit();
2011 unregister_netdevice_notifier(&netconsole_netdev_notifier);
2012
2013 /*
2014 * Targets created via configfs pin references on our module
2015 * and would first be rmdir(2)'ed from userspace. We reach
2016 * here only when they are already destroyed, and only those
2017 * created from the boot/module option are left, so remove and
2018 * destroy them. Skipping the list lock is safe here, and
2019 * netpoll_cleanup() will sleep.
2020 */
2021 list_for_each_entry_safe(nt, tmp, &target_list, list) {
2022 list_del(&nt->list);
2023 free_param_target(nt);
2024 }
2025 }
2026
2027 /*
2028 * Use late_initcall to ensure netconsole is
2029 * initialized after network device driver if built-in.
2030 *
2031 * late_initcall() and module_init() are identical if built as module.
2032 */
2033 late_initcall(init_netconsole);
2034 module_exit(cleanup_netconsole);
2035