Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
43MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
44MODULE_DESCRIPTION("Console driver for network interfaces");
45MODULE_LICENSE("GPL");
46
47#define MAX_PARAM_LENGTH 256
48#define MAX_USERDATA_ENTRY_LENGTH 256
49#define MAX_USERDATA_VALUE_LENGTH 200
50/* The number 3 comes from userdata entry format characters (' ', '=', '\n') */
51#define MAX_USERDATA_NAME_LENGTH (MAX_USERDATA_ENTRY_LENGTH - \
52 MAX_USERDATA_VALUE_LENGTH - 3)
53#define MAX_USERDATA_ITEMS 16
54#define MAX_PRINT_CHUNK 1000
55
56static char config[MAX_PARAM_LENGTH];
57module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
58MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
59
60static bool oops_only;
61module_param(oops_only, bool, 0600);
62MODULE_PARM_DESC(oops_only, "Only log oops messages");
63
64#define NETCONSOLE_PARAM_TARGET_PREFIX "cmdline"
65
66#ifndef MODULE
67static 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 */
76static 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 */
81static LIST_HEAD(target_cleanup_list);
82
83/* This needs to be a spinlock because write_msg() cannot sleep */
84static DEFINE_SPINLOCK(target_list_lock);
85/* This needs to be a mutex because netpoll_cleanup might sleep */
86static DEFINE_MUTEX(target_cleanup_list_lock);
87
88/*
89 * Console driver for extended netconsoles. Registered on the first use to
90 * avoid unnecessarily enabling ext message formatting.
91 */
92static struct console netconsole_ext;
93
94struct 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/**
101 * struct netconsole_target - Represents a configured netconsole target.
102 * @list: Links this target into the target_list.
103 * @group: Links us into the configfs subsystem hierarchy.
104 * @userdata_group: Links to the userdata configfs hierarchy
105 * @userdata_complete: Cached, formatted string of append
106 * @userdata_length: String length of userdata_complete
107 * @stats: Packet send stats for the target. Used for debugging.
108 * @enabled: On / off knob to enable / disable target.
109 * Visible from userspace (read-write).
110 * We maintain a strict 1:1 correspondence between this and
111 * whether the corresponding netpoll is active or inactive.
112 * Also, other parameters of a target may be modified at
113 * runtime only when it is disabled (enabled == 0).
114 * @extended: Denotes whether console is extended or not.
115 * @release: Denotes whether kernel release version should be prepended
116 * to the message. Depends on extended console.
117 * @np: The netpoll structure for this target.
118 * Contains the other userspace visible parameters:
119 * dev_name (read-write)
120 * local_port (read-write)
121 * remote_port (read-write)
122 * local_ip (read-write)
123 * remote_ip (read-write)
124 * local_mac (read-only)
125 * remote_mac (read-write)
126 */
127struct netconsole_target {
128 struct list_head list;
129#ifdef CONFIG_NETCONSOLE_DYNAMIC
130 struct config_group group;
131 struct config_group userdata_group;
132 char userdata_complete[MAX_USERDATA_ENTRY_LENGTH * MAX_USERDATA_ITEMS];
133 size_t userdata_length;
134#endif
135 struct netconsole_target_stats stats;
136 bool enabled;
137 bool extended;
138 bool release;
139 struct netpoll np;
140};
141
142#ifdef CONFIG_NETCONSOLE_DYNAMIC
143
144static struct configfs_subsystem netconsole_subsys;
145static DEFINE_MUTEX(dynamic_netconsole_mutex);
146
147static int __init dynamic_netconsole_init(void)
148{
149 config_group_init(&netconsole_subsys.su_group);
150 mutex_init(&netconsole_subsys.su_mutex);
151 return configfs_register_subsystem(&netconsole_subsys);
152}
153
154static void __exit dynamic_netconsole_exit(void)
155{
156 configfs_unregister_subsystem(&netconsole_subsys);
157}
158
159/*
160 * Targets that were created by parsing the boot/module option string
161 * do not exist in the configfs hierarchy (and have NULL names) and will
162 * never go away, so make these a no-op for them.
163 */
164static void netconsole_target_get(struct netconsole_target *nt)
165{
166 if (config_item_name(&nt->group.cg_item))
167 config_group_get(&nt->group);
168}
169
170static void netconsole_target_put(struct netconsole_target *nt)
171{
172 if (config_item_name(&nt->group.cg_item))
173 config_group_put(&nt->group);
174}
175
176#else /* !CONFIG_NETCONSOLE_DYNAMIC */
177
178static int __init dynamic_netconsole_init(void)
179{
180 return 0;
181}
182
183static void __exit dynamic_netconsole_exit(void)
184{
185}
186
187/*
188 * No danger of targets going away from under us when dynamic
189 * reconfigurability is off.
190 */
191static void netconsole_target_get(struct netconsole_target *nt)
192{
193}
194
195static void netconsole_target_put(struct netconsole_target *nt)
196{
197}
198
199static void populate_configfs_item(struct netconsole_target *nt,
200 int cmdline_count)
201{
202}
203#endif /* CONFIG_NETCONSOLE_DYNAMIC */
204
205/* Allocate and initialize with defaults.
206 * Note that these targets get their config_item fields zeroed-out.
207 */
208static struct netconsole_target *alloc_and_init(void)
209{
210 struct netconsole_target *nt;
211
212 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
213 if (!nt)
214 return nt;
215
216 if (IS_ENABLED(CONFIG_NETCONSOLE_EXTENDED_LOG))
217 nt->extended = true;
218 if (IS_ENABLED(CONFIG_NETCONSOLE_PREPEND_RELEASE))
219 nt->release = true;
220
221 nt->np.name = "netconsole";
222 strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
223 nt->np.local_port = 6665;
224 nt->np.remote_port = 6666;
225 eth_broadcast_addr(nt->np.remote_mac);
226
227 return nt;
228}
229
230/* Clean up every target in the cleanup_list and move the clean targets back to
231 * the main target_list.
232 */
233static void netconsole_process_cleanups_core(void)
234{
235 struct netconsole_target *nt, *tmp;
236 unsigned long flags;
237
238 /* The cleanup needs RTNL locked */
239 ASSERT_RTNL();
240
241 mutex_lock(&target_cleanup_list_lock);
242 list_for_each_entry_safe(nt, tmp, &target_cleanup_list, list) {
243 /* all entries in the cleanup_list needs to be disabled */
244 WARN_ON_ONCE(nt->enabled);
245 do_netpoll_cleanup(&nt->np);
246 /* moved the cleaned target to target_list. Need to hold both
247 * locks
248 */
249 spin_lock_irqsave(&target_list_lock, flags);
250 list_move(&nt->list, &target_list);
251 spin_unlock_irqrestore(&target_list_lock, flags);
252 }
253 WARN_ON_ONCE(!list_empty(&target_cleanup_list));
254 mutex_unlock(&target_cleanup_list_lock);
255}
256
257#ifdef CONFIG_NETCONSOLE_DYNAMIC
258
259/*
260 * Our subsystem hierarchy is:
261 *
262 * /sys/kernel/config/netconsole/
263 * |
264 * <target>/
265 * | enabled
266 * | release
267 * | dev_name
268 * | local_port
269 * | remote_port
270 * | local_ip
271 * | remote_ip
272 * | local_mac
273 * | remote_mac
274 * | transmit_errors
275 * | userdata/
276 * | <key>/
277 * | value
278 * | ...
279 * |
280 * <target>/...
281 */
282
283static struct netconsole_target *to_target(struct config_item *item)
284{
285 struct config_group *cfg_group;
286
287 cfg_group = to_config_group(item);
288 if (!cfg_group)
289 return NULL;
290 return container_of(to_config_group(item),
291 struct netconsole_target, group);
292}
293
294/* Do the list cleanup with the rtnl lock hold. rtnl lock is necessary because
295 * netdev might be cleaned-up by calling __netpoll_cleanup(),
296 */
297static void netconsole_process_cleanups(void)
298{
299 /* rtnl lock is called here, because it has precedence over
300 * target_cleanup_list_lock mutex and target_cleanup_list
301 */
302 rtnl_lock();
303 netconsole_process_cleanups_core();
304 rtnl_unlock();
305}
306
307/* Get rid of possible trailing newline, returning the new length */
308static void trim_newline(char *s, size_t maxlen)
309{
310 size_t len;
311
312 len = strnlen(s, maxlen);
313 if (s[len - 1] == '\n')
314 s[len - 1] = '\0';
315}
316
317/*
318 * Attribute operations for netconsole_target.
319 */
320
321static ssize_t enabled_show(struct config_item *item, char *buf)
322{
323 return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
324}
325
326static ssize_t extended_show(struct config_item *item, char *buf)
327{
328 return sysfs_emit(buf, "%d\n", to_target(item)->extended);
329}
330
331static ssize_t release_show(struct config_item *item, char *buf)
332{
333 return sysfs_emit(buf, "%d\n", to_target(item)->release);
334}
335
336static ssize_t dev_name_show(struct config_item *item, char *buf)
337{
338 return sysfs_emit(buf, "%s\n", to_target(item)->np.dev_name);
339}
340
341static ssize_t local_port_show(struct config_item *item, char *buf)
342{
343 return sysfs_emit(buf, "%d\n", to_target(item)->np.local_port);
344}
345
346static ssize_t remote_port_show(struct config_item *item, char *buf)
347{
348 return sysfs_emit(buf, "%d\n", to_target(item)->np.remote_port);
349}
350
351static ssize_t local_ip_show(struct config_item *item, char *buf)
352{
353 struct netconsole_target *nt = to_target(item);
354
355 if (nt->np.ipv6)
356 return sysfs_emit(buf, "%pI6c\n", &nt->np.local_ip.in6);
357 else
358 return sysfs_emit(buf, "%pI4\n", &nt->np.local_ip);
359}
360
361static ssize_t remote_ip_show(struct config_item *item, char *buf)
362{
363 struct netconsole_target *nt = to_target(item);
364
365 if (nt->np.ipv6)
366 return sysfs_emit(buf, "%pI6c\n", &nt->np.remote_ip.in6);
367 else
368 return sysfs_emit(buf, "%pI4\n", &nt->np.remote_ip);
369}
370
371static ssize_t local_mac_show(struct config_item *item, char *buf)
372{
373 struct net_device *dev = to_target(item)->np.dev;
374 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
375
376 return sysfs_emit(buf, "%pM\n", dev ? dev->dev_addr : bcast);
377}
378
379static ssize_t remote_mac_show(struct config_item *item, char *buf)
380{
381 return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
382}
383
384static ssize_t transmit_errors_show(struct config_item *item, char *buf)
385{
386 struct netconsole_target *nt = to_target(item);
387 u64 xmit_drop_count, enomem_count;
388 unsigned int start;
389
390 do {
391 start = u64_stats_fetch_begin(&nt->stats.syncp);
392 xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
393 enomem_count = u64_stats_read(&nt->stats.enomem_count);
394 } while (u64_stats_fetch_retry(&nt->stats.syncp, start));
395
396 return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
397}
398
399/*
400 * This one is special -- targets created through the configfs interface
401 * are not enabled (and the corresponding netpoll activated) by default.
402 * The user is expected to set the desired parameters first (which
403 * would enable him to dynamically add new netpoll targets for new
404 * network interfaces as and when they come up).
405 */
406static ssize_t enabled_store(struct config_item *item,
407 const char *buf, size_t count)
408{
409 struct netconsole_target *nt = to_target(item);
410 unsigned long flags;
411 bool enabled;
412 ssize_t ret;
413
414 mutex_lock(&dynamic_netconsole_mutex);
415 ret = kstrtobool(buf, &enabled);
416 if (ret)
417 goto out_unlock;
418
419 ret = -EINVAL;
420 if (enabled == nt->enabled) {
421 pr_info("network logging has already %s\n",
422 nt->enabled ? "started" : "stopped");
423 goto out_unlock;
424 }
425
426 if (enabled) { /* true */
427 if (nt->release && !nt->extended) {
428 pr_err("Not enabling netconsole. Release feature requires extended log message");
429 goto out_unlock;
430 }
431
432 if (nt->extended && !console_is_registered(&netconsole_ext))
433 register_console(&netconsole_ext);
434
435 /*
436 * Skip netpoll_parse_options() -- all the attributes are
437 * already configured via configfs. Just print them out.
438 */
439 netpoll_print_options(&nt->np);
440
441 ret = netpoll_setup(&nt->np);
442 if (ret)
443 goto out_unlock;
444
445 nt->enabled = true;
446 pr_info("network logging started\n");
447 } else { /* false */
448 /* We need to disable the netconsole before cleaning it up
449 * otherwise we might end up in write_msg() with
450 * nt->np.dev == NULL and nt->enabled == true
451 */
452 mutex_lock(&target_cleanup_list_lock);
453 spin_lock_irqsave(&target_list_lock, flags);
454 nt->enabled = false;
455 /* Remove the target from the list, while holding
456 * target_list_lock
457 */
458 list_move(&nt->list, &target_cleanup_list);
459 spin_unlock_irqrestore(&target_list_lock, flags);
460 mutex_unlock(&target_cleanup_list_lock);
461 }
462
463 ret = strnlen(buf, count);
464 /* Deferred cleanup */
465 netconsole_process_cleanups();
466out_unlock:
467 mutex_unlock(&dynamic_netconsole_mutex);
468 return ret;
469}
470
471static ssize_t release_store(struct config_item *item, const char *buf,
472 size_t count)
473{
474 struct netconsole_target *nt = to_target(item);
475 bool release;
476 ssize_t ret;
477
478 mutex_lock(&dynamic_netconsole_mutex);
479 if (nt->enabled) {
480 pr_err("target (%s) is enabled, disable to update parameters\n",
481 config_item_name(&nt->group.cg_item));
482 ret = -EINVAL;
483 goto out_unlock;
484 }
485
486 ret = kstrtobool(buf, &release);
487 if (ret)
488 goto out_unlock;
489
490 nt->release = release;
491
492 ret = strnlen(buf, count);
493out_unlock:
494 mutex_unlock(&dynamic_netconsole_mutex);
495 return ret;
496}
497
498static ssize_t extended_store(struct config_item *item, const char *buf,
499 size_t count)
500{
501 struct netconsole_target *nt = to_target(item);
502 bool extended;
503 ssize_t ret;
504
505 mutex_lock(&dynamic_netconsole_mutex);
506 if (nt->enabled) {
507 pr_err("target (%s) is enabled, disable to update parameters\n",
508 config_item_name(&nt->group.cg_item));
509 ret = -EINVAL;
510 goto out_unlock;
511 }
512
513 ret = kstrtobool(buf, &extended);
514 if (ret)
515 goto out_unlock;
516
517 nt->extended = extended;
518 ret = strnlen(buf, count);
519out_unlock:
520 mutex_unlock(&dynamic_netconsole_mutex);
521 return ret;
522}
523
524static ssize_t dev_name_store(struct config_item *item, const char *buf,
525 size_t count)
526{
527 struct netconsole_target *nt = to_target(item);
528
529 mutex_lock(&dynamic_netconsole_mutex);
530 if (nt->enabled) {
531 pr_err("target (%s) is enabled, disable to update parameters\n",
532 config_item_name(&nt->group.cg_item));
533 mutex_unlock(&dynamic_netconsole_mutex);
534 return -EINVAL;
535 }
536
537 strscpy(nt->np.dev_name, buf, IFNAMSIZ);
538 trim_newline(nt->np.dev_name, IFNAMSIZ);
539
540 mutex_unlock(&dynamic_netconsole_mutex);
541 return strnlen(buf, count);
542}
543
544static ssize_t local_port_store(struct config_item *item, const char *buf,
545 size_t count)
546{
547 struct netconsole_target *nt = to_target(item);
548 ssize_t ret = -EINVAL;
549
550 mutex_lock(&dynamic_netconsole_mutex);
551 if (nt->enabled) {
552 pr_err("target (%s) is enabled, disable to update parameters\n",
553 config_item_name(&nt->group.cg_item));
554 goto out_unlock;
555 }
556
557 ret = kstrtou16(buf, 10, &nt->np.local_port);
558 if (ret < 0)
559 goto out_unlock;
560 ret = strnlen(buf, count);
561out_unlock:
562 mutex_unlock(&dynamic_netconsole_mutex);
563 return ret;
564}
565
566static ssize_t remote_port_store(struct config_item *item,
567 const char *buf, size_t count)
568{
569 struct netconsole_target *nt = to_target(item);
570 ssize_t ret = -EINVAL;
571
572 mutex_lock(&dynamic_netconsole_mutex);
573 if (nt->enabled) {
574 pr_err("target (%s) is enabled, disable to update parameters\n",
575 config_item_name(&nt->group.cg_item));
576 goto out_unlock;
577 }
578
579 ret = kstrtou16(buf, 10, &nt->np.remote_port);
580 if (ret < 0)
581 goto out_unlock;
582 ret = strnlen(buf, count);
583out_unlock:
584 mutex_unlock(&dynamic_netconsole_mutex);
585 return ret;
586}
587
588static ssize_t local_ip_store(struct config_item *item, const char *buf,
589 size_t count)
590{
591 struct netconsole_target *nt = to_target(item);
592 ssize_t ret = -EINVAL;
593
594 mutex_lock(&dynamic_netconsole_mutex);
595 if (nt->enabled) {
596 pr_err("target (%s) is enabled, disable to update parameters\n",
597 config_item_name(&nt->group.cg_item));
598 goto out_unlock;
599 }
600
601 if (strnchr(buf, count, ':')) {
602 const char *end;
603
604 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
605 if (*end && *end != '\n') {
606 pr_err("invalid IPv6 address at: <%c>\n", *end);
607 goto out_unlock;
608 }
609 nt->np.ipv6 = true;
610 } else
611 goto out_unlock;
612 } else {
613 if (!nt->np.ipv6)
614 nt->np.local_ip.ip = in_aton(buf);
615 else
616 goto out_unlock;
617 }
618
619 ret = strnlen(buf, count);
620out_unlock:
621 mutex_unlock(&dynamic_netconsole_mutex);
622 return ret;
623}
624
625static ssize_t remote_ip_store(struct config_item *item, const char *buf,
626 size_t count)
627{
628 struct netconsole_target *nt = to_target(item);
629 ssize_t ret = -EINVAL;
630
631 mutex_lock(&dynamic_netconsole_mutex);
632 if (nt->enabled) {
633 pr_err("target (%s) is enabled, disable to update parameters\n",
634 config_item_name(&nt->group.cg_item));
635 goto out_unlock;
636 }
637
638 if (strnchr(buf, count, ':')) {
639 const char *end;
640
641 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
642 if (*end && *end != '\n') {
643 pr_err("invalid IPv6 address at: <%c>\n", *end);
644 goto out_unlock;
645 }
646 nt->np.ipv6 = true;
647 } else
648 goto out_unlock;
649 } else {
650 if (!nt->np.ipv6)
651 nt->np.remote_ip.ip = in_aton(buf);
652 else
653 goto out_unlock;
654 }
655
656 ret = strnlen(buf, count);
657out_unlock:
658 mutex_unlock(&dynamic_netconsole_mutex);
659 return ret;
660}
661
662static ssize_t remote_mac_store(struct config_item *item, const char *buf,
663 size_t count)
664{
665 struct netconsole_target *nt = to_target(item);
666 u8 remote_mac[ETH_ALEN];
667 ssize_t ret = -EINVAL;
668
669 mutex_lock(&dynamic_netconsole_mutex);
670 if (nt->enabled) {
671 pr_err("target (%s) is enabled, disable to update parameters\n",
672 config_item_name(&nt->group.cg_item));
673 goto out_unlock;
674 }
675
676 if (!mac_pton(buf, remote_mac))
677 goto out_unlock;
678 if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
679 goto out_unlock;
680 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
681
682 ret = strnlen(buf, count);
683out_unlock:
684 mutex_unlock(&dynamic_netconsole_mutex);
685 return ret;
686}
687
688struct userdatum {
689 struct config_item item;
690 char value[MAX_USERDATA_VALUE_LENGTH];
691};
692
693static struct userdatum *to_userdatum(struct config_item *item)
694{
695 return container_of(item, struct userdatum, item);
696}
697
698struct userdata {
699 struct config_group group;
700};
701
702static struct userdata *to_userdata(struct config_item *item)
703{
704 return container_of(to_config_group(item), struct userdata, group);
705}
706
707static struct netconsole_target *userdata_to_target(struct userdata *ud)
708{
709 struct config_group *netconsole_group;
710
711 netconsole_group = to_config_group(ud->group.cg_item.ci_parent);
712 return to_target(&netconsole_group->cg_item);
713}
714
715static ssize_t userdatum_value_show(struct config_item *item, char *buf)
716{
717 return sysfs_emit(buf, "%s\n", &(to_userdatum(item)->value[0]));
718}
719
720static void update_userdata(struct netconsole_target *nt)
721{
722 int complete_idx = 0, child_count = 0;
723 struct list_head *entry;
724
725 /* Clear the current string in case the last userdatum was deleted */
726 nt->userdata_length = 0;
727 nt->userdata_complete[0] = 0;
728
729 list_for_each(entry, &nt->userdata_group.cg_children) {
730 struct userdatum *udm_item;
731 struct config_item *item;
732
733 if (WARN_ON_ONCE(child_count >= MAX_USERDATA_ITEMS))
734 break;
735 child_count++;
736
737 item = container_of(entry, struct config_item, ci_entry);
738 udm_item = to_userdatum(item);
739
740 /* Skip userdata with no value set */
741 if (strnlen(udm_item->value, MAX_USERDATA_VALUE_LENGTH) == 0)
742 continue;
743
744 /* This doesn't overflow userdata_complete since it will write
745 * one entry length (1/MAX_USERDATA_ITEMS long), entry count is
746 * checked to not exceed MAX items with child_count above
747 */
748 complete_idx += scnprintf(&nt->userdata_complete[complete_idx],
749 MAX_USERDATA_ENTRY_LENGTH, " %s=%s\n",
750 item->ci_name, udm_item->value);
751 }
752 nt->userdata_length = strnlen(nt->userdata_complete,
753 sizeof(nt->userdata_complete));
754}
755
756static ssize_t userdatum_value_store(struct config_item *item, const char *buf,
757 size_t count)
758{
759 struct userdatum *udm = to_userdatum(item);
760 struct netconsole_target *nt;
761 struct userdata *ud;
762 ssize_t ret;
763
764 if (count > MAX_USERDATA_VALUE_LENGTH)
765 return -EMSGSIZE;
766
767 mutex_lock(&dynamic_netconsole_mutex);
768
769 ret = strscpy(udm->value, buf, sizeof(udm->value));
770 if (ret < 0)
771 goto out_unlock;
772 trim_newline(udm->value, sizeof(udm->value));
773
774 ud = to_userdata(item->ci_parent);
775 nt = userdata_to_target(ud);
776 update_userdata(nt);
777 ret = count;
778out_unlock:
779 mutex_unlock(&dynamic_netconsole_mutex);
780 return ret;
781}
782
783CONFIGFS_ATTR(userdatum_, value);
784
785static struct configfs_attribute *userdatum_attrs[] = {
786 &userdatum_attr_value,
787 NULL,
788};
789
790static void userdatum_release(struct config_item *item)
791{
792 kfree(to_userdatum(item));
793}
794
795static struct configfs_item_operations userdatum_ops = {
796 .release = userdatum_release,
797};
798
799static const struct config_item_type userdatum_type = {
800 .ct_item_ops = &userdatum_ops,
801 .ct_attrs = userdatum_attrs,
802 .ct_owner = THIS_MODULE,
803};
804
805static struct config_item *userdatum_make_item(struct config_group *group,
806 const char *name)
807{
808 struct netconsole_target *nt;
809 struct userdatum *udm;
810 struct userdata *ud;
811 size_t child_count;
812
813 if (strlen(name) > MAX_USERDATA_NAME_LENGTH)
814 return ERR_PTR(-ENAMETOOLONG);
815
816 ud = to_userdata(&group->cg_item);
817 nt = userdata_to_target(ud);
818 child_count = list_count_nodes(&nt->userdata_group.cg_children);
819 if (child_count >= MAX_USERDATA_ITEMS)
820 return ERR_PTR(-ENOSPC);
821
822 udm = kzalloc(sizeof(*udm), GFP_KERNEL);
823 if (!udm)
824 return ERR_PTR(-ENOMEM);
825
826 config_item_init_type_name(&udm->item, name, &userdatum_type);
827 return &udm->item;
828}
829
830static void userdatum_drop(struct config_group *group, struct config_item *item)
831{
832 struct netconsole_target *nt;
833 struct userdata *ud;
834
835 ud = to_userdata(&group->cg_item);
836 nt = userdata_to_target(ud);
837
838 mutex_lock(&dynamic_netconsole_mutex);
839 update_userdata(nt);
840 config_item_put(item);
841 mutex_unlock(&dynamic_netconsole_mutex);
842}
843
844static struct configfs_attribute *userdata_attrs[] = {
845 NULL,
846};
847
848static struct configfs_group_operations userdata_ops = {
849 .make_item = userdatum_make_item,
850 .drop_item = userdatum_drop,
851};
852
853static const struct config_item_type userdata_type = {
854 .ct_item_ops = &userdatum_ops,
855 .ct_group_ops = &userdata_ops,
856 .ct_attrs = userdata_attrs,
857 .ct_owner = THIS_MODULE,
858};
859
860CONFIGFS_ATTR(, enabled);
861CONFIGFS_ATTR(, extended);
862CONFIGFS_ATTR(, dev_name);
863CONFIGFS_ATTR(, local_port);
864CONFIGFS_ATTR(, remote_port);
865CONFIGFS_ATTR(, local_ip);
866CONFIGFS_ATTR(, remote_ip);
867CONFIGFS_ATTR_RO(, local_mac);
868CONFIGFS_ATTR(, remote_mac);
869CONFIGFS_ATTR(, release);
870CONFIGFS_ATTR_RO(, transmit_errors);
871
872static struct configfs_attribute *netconsole_target_attrs[] = {
873 &attr_enabled,
874 &attr_extended,
875 &attr_release,
876 &attr_dev_name,
877 &attr_local_port,
878 &attr_remote_port,
879 &attr_local_ip,
880 &attr_remote_ip,
881 &attr_local_mac,
882 &attr_remote_mac,
883 &attr_transmit_errors,
884 NULL,
885};
886
887/*
888 * Item operations and type for netconsole_target.
889 */
890
891static void netconsole_target_release(struct config_item *item)
892{
893 kfree(to_target(item));
894}
895
896static struct configfs_item_operations netconsole_target_item_ops = {
897 .release = netconsole_target_release,
898};
899
900static const struct config_item_type netconsole_target_type = {
901 .ct_attrs = netconsole_target_attrs,
902 .ct_item_ops = &netconsole_target_item_ops,
903 .ct_owner = THIS_MODULE,
904};
905
906static void init_target_config_group(struct netconsole_target *nt,
907 const char *name)
908{
909 config_group_init_type_name(&nt->group, name, &netconsole_target_type);
910 config_group_init_type_name(&nt->userdata_group, "userdata",
911 &userdata_type);
912 configfs_add_default_group(&nt->userdata_group, &nt->group);
913}
914
915static struct netconsole_target *find_cmdline_target(const char *name)
916{
917 struct netconsole_target *nt, *ret = NULL;
918 unsigned long flags;
919
920 spin_lock_irqsave(&target_list_lock, flags);
921 list_for_each_entry(nt, &target_list, list) {
922 if (!strcmp(nt->group.cg_item.ci_name, name)) {
923 ret = nt;
924 break;
925 }
926 }
927 spin_unlock_irqrestore(&target_list_lock, flags);
928
929 return ret;
930}
931
932/*
933 * Group operations and type for netconsole_subsys.
934 */
935
936static struct config_group *make_netconsole_target(struct config_group *group,
937 const char *name)
938{
939 struct netconsole_target *nt;
940 unsigned long flags;
941
942 /* Checking if a target by this name was created at boot time. If so,
943 * attach a configfs entry to that target. This enables dynamic
944 * control.
945 */
946 if (!strncmp(name, NETCONSOLE_PARAM_TARGET_PREFIX,
947 strlen(NETCONSOLE_PARAM_TARGET_PREFIX))) {
948 nt = find_cmdline_target(name);
949 if (nt) {
950 init_target_config_group(nt, name);
951 return &nt->group;
952 }
953 }
954
955 nt = alloc_and_init();
956 if (!nt)
957 return ERR_PTR(-ENOMEM);
958
959 /* Initialize the config_group member */
960 init_target_config_group(nt, name);
961
962 /* Adding, but it is disabled */
963 spin_lock_irqsave(&target_list_lock, flags);
964 list_add(&nt->list, &target_list);
965 spin_unlock_irqrestore(&target_list_lock, flags);
966
967 return &nt->group;
968}
969
970static void drop_netconsole_target(struct config_group *group,
971 struct config_item *item)
972{
973 unsigned long flags;
974 struct netconsole_target *nt = to_target(item);
975
976 spin_lock_irqsave(&target_list_lock, flags);
977 list_del(&nt->list);
978 spin_unlock_irqrestore(&target_list_lock, flags);
979
980 /*
981 * The target may have never been enabled, or was manually disabled
982 * before being removed so netpoll may have already been cleaned up.
983 */
984 if (nt->enabled)
985 netpoll_cleanup(&nt->np);
986
987 config_item_put(&nt->group.cg_item);
988}
989
990static struct configfs_group_operations netconsole_subsys_group_ops = {
991 .make_group = make_netconsole_target,
992 .drop_item = drop_netconsole_target,
993};
994
995static const struct config_item_type netconsole_subsys_type = {
996 .ct_group_ops = &netconsole_subsys_group_ops,
997 .ct_owner = THIS_MODULE,
998};
999
1000/* The netconsole configfs subsystem */
1001static struct configfs_subsystem netconsole_subsys = {
1002 .su_group = {
1003 .cg_item = {
1004 .ci_namebuf = "netconsole",
1005 .ci_type = &netconsole_subsys_type,
1006 },
1007 },
1008};
1009
1010static void populate_configfs_item(struct netconsole_target *nt,
1011 int cmdline_count)
1012{
1013 char target_name[16];
1014
1015 snprintf(target_name, sizeof(target_name), "%s%d",
1016 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1017 init_target_config_group(nt, target_name);
1018}
1019
1020#endif /* CONFIG_NETCONSOLE_DYNAMIC */
1021
1022/* Handle network interface device notifications */
1023static int netconsole_netdev_event(struct notifier_block *this,
1024 unsigned long event, void *ptr)
1025{
1026 unsigned long flags;
1027 struct netconsole_target *nt, *tmp;
1028 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1029 bool stopped = false;
1030
1031 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
1032 event == NETDEV_RELEASE || event == NETDEV_JOIN))
1033 goto done;
1034
1035 mutex_lock(&target_cleanup_list_lock);
1036 spin_lock_irqsave(&target_list_lock, flags);
1037 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1038 netconsole_target_get(nt);
1039 if (nt->np.dev == dev) {
1040 switch (event) {
1041 case NETDEV_CHANGENAME:
1042 strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
1043 break;
1044 case NETDEV_RELEASE:
1045 case NETDEV_JOIN:
1046 case NETDEV_UNREGISTER:
1047 nt->enabled = false;
1048 list_move(&nt->list, &target_cleanup_list);
1049 stopped = true;
1050 }
1051 }
1052 netconsole_target_put(nt);
1053 }
1054 spin_unlock_irqrestore(&target_list_lock, flags);
1055 mutex_unlock(&target_cleanup_list_lock);
1056
1057 if (stopped) {
1058 const char *msg = "had an event";
1059
1060 switch (event) {
1061 case NETDEV_UNREGISTER:
1062 msg = "unregistered";
1063 break;
1064 case NETDEV_RELEASE:
1065 msg = "released slaves";
1066 break;
1067 case NETDEV_JOIN:
1068 msg = "is joining a master device";
1069 break;
1070 }
1071 pr_info("network logging stopped on interface %s as it %s\n",
1072 dev->name, msg);
1073 }
1074
1075 /* Process target_cleanup_list entries. By the end, target_cleanup_list
1076 * should be empty
1077 */
1078 netconsole_process_cleanups_core();
1079
1080done:
1081 return NOTIFY_DONE;
1082}
1083
1084static struct notifier_block netconsole_netdev_notifier = {
1085 .notifier_call = netconsole_netdev_event,
1086};
1087
1088/**
1089 * send_udp - Wrapper for netpoll_send_udp that counts errors
1090 * @nt: target to send message to
1091 * @msg: message to send
1092 * @len: length of message
1093 *
1094 * Calls netpoll_send_udp and classifies the return value. If an error
1095 * occurred it increments statistics in nt->stats accordingly.
1096 * Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
1097 */
1098static void send_udp(struct netconsole_target *nt, const char *msg, int len)
1099{
1100 int result = netpoll_send_udp(&nt->np, msg, len);
1101
1102 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
1103 if (result == NET_XMIT_DROP) {
1104 u64_stats_update_begin(&nt->stats.syncp);
1105 u64_stats_inc(&nt->stats.xmit_drop_count);
1106 u64_stats_update_end(&nt->stats.syncp);
1107 } else if (result == -ENOMEM) {
1108 u64_stats_update_begin(&nt->stats.syncp);
1109 u64_stats_inc(&nt->stats.enomem_count);
1110 u64_stats_update_end(&nt->stats.syncp);
1111 }
1112 }
1113}
1114
1115static void send_msg_no_fragmentation(struct netconsole_target *nt,
1116 const char *msg,
1117 int msg_len,
1118 int release_len)
1119{
1120 static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
1121 const char *userdata = NULL;
1122 const char *release;
1123
1124#ifdef CONFIG_NETCONSOLE_DYNAMIC
1125 userdata = nt->userdata_complete;
1126#endif
1127
1128 if (release_len) {
1129 release = init_utsname()->release;
1130
1131 scnprintf(buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
1132 msg_len += release_len;
1133 } else {
1134 memcpy(buf, msg, msg_len);
1135 }
1136
1137 if (userdata)
1138 msg_len += scnprintf(&buf[msg_len],
1139 MAX_PRINT_CHUNK - msg_len,
1140 "%s", userdata);
1141
1142 send_udp(nt, buf, msg_len);
1143}
1144
1145static void append_release(char *buf)
1146{
1147 const char *release;
1148
1149 release = init_utsname()->release;
1150 scnprintf(buf, MAX_PRINT_CHUNK, "%s,", release);
1151}
1152
1153static void send_fragmented_body(struct netconsole_target *nt, char *buf,
1154 const char *msgbody, int header_len,
1155 int msgbody_len)
1156{
1157 const char *userdata = NULL;
1158 int body_len, offset = 0;
1159 int userdata_len = 0;
1160
1161#ifdef CONFIG_NETCONSOLE_DYNAMIC
1162 userdata = nt->userdata_complete;
1163 userdata_len = nt->userdata_length;
1164#endif
1165
1166 /* body_len represents the number of bytes that will be sent. This is
1167 * bigger than MAX_PRINT_CHUNK, thus, it will be split in multiple
1168 * packets
1169 */
1170 body_len = msgbody_len + userdata_len;
1171
1172 /* In each iteration of the while loop below, we send a packet
1173 * containing the header and a portion of the body. The body is
1174 * composed of two parts: msgbody and userdata. We keep track of how
1175 * many bytes have been sent so far using the offset variable, which
1176 * ranges from 0 to the total length of the body.
1177 */
1178 while (offset < body_len) {
1179 int this_header = header_len;
1180 bool msgbody_written = false;
1181 int this_offset = 0;
1182 int this_chunk = 0;
1183
1184 this_header += scnprintf(buf + this_header,
1185 MAX_PRINT_CHUNK - this_header,
1186 ",ncfrag=%d/%d;", offset,
1187 body_len);
1188
1189 /* Not all msgbody data has been written yet */
1190 if (offset < msgbody_len) {
1191 this_chunk = min(msgbody_len - offset,
1192 MAX_PRINT_CHUNK - this_header);
1193 if (WARN_ON_ONCE(this_chunk <= 0))
1194 return;
1195 memcpy(buf + this_header, msgbody + offset, this_chunk);
1196 this_offset += this_chunk;
1197 }
1198
1199 /* msgbody was finally written, either in the previous
1200 * messages and/or in the current buf. Time to write
1201 * the userdata.
1202 */
1203 msgbody_written |= offset + this_offset >= msgbody_len;
1204
1205 /* Msg body is fully written and there is pending userdata to
1206 * write, append userdata in this chunk
1207 */
1208 if (msgbody_written && offset + this_offset < body_len) {
1209 /* Track how much user data was already sent. First
1210 * time here, sent_userdata is zero
1211 */
1212 int sent_userdata = (offset + this_offset) - msgbody_len;
1213 /* offset of bytes used in current buf */
1214 int preceding_bytes = this_chunk + this_header;
1215
1216 if (WARN_ON_ONCE(sent_userdata < 0))
1217 return;
1218
1219 this_chunk = min(userdata_len - sent_userdata,
1220 MAX_PRINT_CHUNK - preceding_bytes);
1221 if (WARN_ON_ONCE(this_chunk < 0))
1222 /* this_chunk could be zero if all the previous
1223 * message used all the buffer. This is not a
1224 * problem, userdata will be sent in the next
1225 * iteration
1226 */
1227 return;
1228
1229 memcpy(buf + this_header + this_offset,
1230 userdata + sent_userdata,
1231 this_chunk);
1232 this_offset += this_chunk;
1233 }
1234
1235 send_udp(nt, buf, this_header + this_offset);
1236 offset += this_offset;
1237 }
1238}
1239
1240static void send_msg_fragmented(struct netconsole_target *nt,
1241 const char *msg,
1242 int msg_len,
1243 int release_len)
1244{
1245 static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
1246 int header_len, msgbody_len;
1247 const char *msgbody;
1248
1249 /* need to insert extra header fields, detect header and msgbody */
1250 msgbody = memchr(msg, ';', msg_len);
1251 if (WARN_ON_ONCE(!msgbody))
1252 return;
1253
1254 header_len = msgbody - msg;
1255 msgbody_len = msg_len - header_len - 1;
1256 msgbody++;
1257
1258 /*
1259 * Transfer multiple chunks with the following extra header.
1260 * "ncfrag=<byte-offset>/<total-bytes>"
1261 */
1262 if (release_len)
1263 append_release(buf);
1264
1265 /* Copy the header into the buffer */
1266 memcpy(buf + release_len, msg, header_len);
1267 header_len += release_len;
1268
1269 /* for now on, the header will be persisted, and the msgbody
1270 * will be replaced
1271 */
1272 send_fragmented_body(nt, buf, msgbody, header_len, msgbody_len);
1273}
1274
1275/**
1276 * send_ext_msg_udp - send extended log message to target
1277 * @nt: target to send message to
1278 * @msg: extended log message to send
1279 * @msg_len: length of message
1280 *
1281 * Transfer extended log @msg to @nt. If @msg is longer than
1282 * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
1283 * ncfrag header field added to identify them.
1284 */
1285static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
1286 int msg_len)
1287{
1288 int userdata_len = 0;
1289 int release_len = 0;
1290
1291#ifdef CONFIG_NETCONSOLE_DYNAMIC
1292 userdata_len = nt->userdata_length;
1293#endif
1294
1295 if (nt->release)
1296 release_len = strlen(init_utsname()->release) + 1;
1297
1298 if (msg_len + release_len + userdata_len <= MAX_PRINT_CHUNK)
1299 return send_msg_no_fragmentation(nt, msg, msg_len, release_len);
1300
1301 return send_msg_fragmented(nt, msg, msg_len, release_len);
1302}
1303
1304static void write_ext_msg(struct console *con, const char *msg,
1305 unsigned int len)
1306{
1307 struct netconsole_target *nt;
1308 unsigned long flags;
1309
1310 if ((oops_only && !oops_in_progress) || list_empty(&target_list))
1311 return;
1312
1313 spin_lock_irqsave(&target_list_lock, flags);
1314 list_for_each_entry(nt, &target_list, list)
1315 if (nt->extended && nt->enabled && netif_running(nt->np.dev))
1316 send_ext_msg_udp(nt, msg, len);
1317 spin_unlock_irqrestore(&target_list_lock, flags);
1318}
1319
1320static void write_msg(struct console *con, const char *msg, unsigned int len)
1321{
1322 int frag, left;
1323 unsigned long flags;
1324 struct netconsole_target *nt;
1325 const char *tmp;
1326
1327 if (oops_only && !oops_in_progress)
1328 return;
1329 /* Avoid taking lock and disabling interrupts unnecessarily */
1330 if (list_empty(&target_list))
1331 return;
1332
1333 spin_lock_irqsave(&target_list_lock, flags);
1334 list_for_each_entry(nt, &target_list, list) {
1335 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {
1336 /*
1337 * We nest this inside the for-each-target loop above
1338 * so that we're able to get as much logging out to
1339 * at least one target if we die inside here, instead
1340 * of unnecessarily keeping all targets in lock-step.
1341 */
1342 tmp = msg;
1343 for (left = len; left;) {
1344 frag = min(left, MAX_PRINT_CHUNK);
1345 send_udp(nt, tmp, frag);
1346 tmp += frag;
1347 left -= frag;
1348 }
1349 }
1350 }
1351 spin_unlock_irqrestore(&target_list_lock, flags);
1352}
1353
1354/* Allocate new target (from boot/module param) and setup netpoll for it */
1355static struct netconsole_target *alloc_param_target(char *target_config,
1356 int cmdline_count)
1357{
1358 struct netconsole_target *nt;
1359 int err;
1360
1361 nt = alloc_and_init();
1362 if (!nt) {
1363 err = -ENOMEM;
1364 goto fail;
1365 }
1366
1367 if (*target_config == '+') {
1368 nt->extended = true;
1369 target_config++;
1370 }
1371
1372 if (*target_config == 'r') {
1373 if (!nt->extended) {
1374 pr_err("Netconsole configuration error. Release feature requires extended log message");
1375 err = -EINVAL;
1376 goto fail;
1377 }
1378 nt->release = true;
1379 target_config++;
1380 }
1381
1382 /* Parse parameters and setup netpoll */
1383 err = netpoll_parse_options(&nt->np, target_config);
1384 if (err)
1385 goto fail;
1386
1387 err = netpoll_setup(&nt->np);
1388 if (err) {
1389 pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
1390 NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
1391 if (!IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1392 /* only fail if dynamic reconfiguration is set,
1393 * otherwise, keep the target in the list, but disabled.
1394 */
1395 goto fail;
1396 } else {
1397 nt->enabled = true;
1398 }
1399 populate_configfs_item(nt, cmdline_count);
1400
1401 return nt;
1402
1403fail:
1404 kfree(nt);
1405 return ERR_PTR(err);
1406}
1407
1408/* Cleanup netpoll for given target (from boot/module param) and free it */
1409static void free_param_target(struct netconsole_target *nt)
1410{
1411 netpoll_cleanup(&nt->np);
1412 kfree(nt);
1413}
1414
1415static struct console netconsole_ext = {
1416 .name = "netcon_ext",
1417 .flags = CON_ENABLED | CON_EXTENDED,
1418 .write = write_ext_msg,
1419};
1420
1421static struct console netconsole = {
1422 .name = "netcon",
1423 .flags = CON_ENABLED,
1424 .write = write_msg,
1425};
1426
1427static int __init init_netconsole(void)
1428{
1429 int err;
1430 struct netconsole_target *nt, *tmp;
1431 unsigned int count = 0;
1432 bool extended = false;
1433 unsigned long flags;
1434 char *target_config;
1435 char *input = config;
1436
1437 if (strnlen(input, MAX_PARAM_LENGTH)) {
1438 while ((target_config = strsep(&input, ";"))) {
1439 nt = alloc_param_target(target_config, count);
1440 if (IS_ERR(nt)) {
1441 if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC))
1442 continue;
1443 err = PTR_ERR(nt);
1444 goto fail;
1445 }
1446 /* Dump existing printks when we register */
1447 if (nt->extended) {
1448 extended = true;
1449 netconsole_ext.flags |= CON_PRINTBUFFER;
1450 } else {
1451 netconsole.flags |= CON_PRINTBUFFER;
1452 }
1453
1454 spin_lock_irqsave(&target_list_lock, flags);
1455 list_add(&nt->list, &target_list);
1456 spin_unlock_irqrestore(&target_list_lock, flags);
1457 count++;
1458 }
1459 }
1460
1461 err = register_netdevice_notifier(&netconsole_netdev_notifier);
1462 if (err)
1463 goto fail;
1464
1465 err = dynamic_netconsole_init();
1466 if (err)
1467 goto undonotifier;
1468
1469 if (extended)
1470 register_console(&netconsole_ext);
1471 register_console(&netconsole);
1472 pr_info("network logging started\n");
1473
1474 return err;
1475
1476undonotifier:
1477 unregister_netdevice_notifier(&netconsole_netdev_notifier);
1478
1479fail:
1480 pr_err("cleaning up\n");
1481
1482 /*
1483 * Remove all targets and destroy them (only targets created
1484 * from the boot/module option exist here). Skipping the list
1485 * lock is safe here, and netpoll_cleanup() will sleep.
1486 */
1487 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1488 list_del(&nt->list);
1489 free_param_target(nt);
1490 }
1491
1492 return err;
1493}
1494
1495static void __exit cleanup_netconsole(void)
1496{
1497 struct netconsole_target *nt, *tmp;
1498
1499 if (console_is_registered(&netconsole_ext))
1500 unregister_console(&netconsole_ext);
1501 unregister_console(&netconsole);
1502 dynamic_netconsole_exit();
1503 unregister_netdevice_notifier(&netconsole_netdev_notifier);
1504
1505 /*
1506 * Targets created via configfs pin references on our module
1507 * and would first be rmdir(2)'ed from userspace. We reach
1508 * here only when they are already destroyed, and only those
1509 * created from the boot/module option are left, so remove and
1510 * destroy them. Skipping the list lock is safe here, and
1511 * netpoll_cleanup() will sleep.
1512 */
1513 list_for_each_entry_safe(nt, tmp, &target_list, list) {
1514 list_del(&nt->list);
1515 free_param_target(nt);
1516 }
1517}
1518
1519/*
1520 * Use late_initcall to ensure netconsole is
1521 * initialized after network device driver if built-in.
1522 *
1523 * late_initcall() and module_init() are identical if built as module.
1524 */
1525late_initcall(init_netconsole);
1526module_exit(cleanup_netconsole);