]> Git Repo - linux.git/blob - drivers/net/netconsole.c
Merge tag 'riscv-for-linus-6.14-mw1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / drivers / net / netconsole.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  linux/drivers/net/netconsole.c
4  *
5  *  Copyright (C) 2001  Ingo Molnar <[email protected]>
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 <[email protected]>");
44 MODULE_DESCRIPTION("Console driver for network interfaces");
45 MODULE_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
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
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 extended netconsoles.  Registered on the first use to
90  * avoid unnecessarily enabling ext message formatting.
91  */
92 static struct console netconsole_ext;
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 /**
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  */
127 struct 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
144 static struct configfs_subsystem netconsole_subsys;
145 static DEFINE_MUTEX(dynamic_netconsole_mutex);
146
147 static 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
154 static 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  */
164 static 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
170 static 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
178 static int __init dynamic_netconsole_init(void)
179 {
180         return 0;
181 }
182
183 static 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  */
191 static void netconsole_target_get(struct netconsole_target *nt)
192 {
193 }
194
195 static void netconsole_target_put(struct netconsole_target *nt)
196 {
197 }
198
199 static 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  */
208 static 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  */
233 static 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
283 static 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  */
297 static 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 */
308 static 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
321 static ssize_t enabled_show(struct config_item *item, char *buf)
322 {
323         return sysfs_emit(buf, "%d\n", to_target(item)->enabled);
324 }
325
326 static ssize_t extended_show(struct config_item *item, char *buf)
327 {
328         return sysfs_emit(buf, "%d\n", to_target(item)->extended);
329 }
330
331 static ssize_t release_show(struct config_item *item, char *buf)
332 {
333         return sysfs_emit(buf, "%d\n", to_target(item)->release);
334 }
335
336 static 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
341 static 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
346 static 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
351 static 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
361 static 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
371 static 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
379 static 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
384 static 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  */
406 static 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();
466 out_unlock:
467         mutex_unlock(&dynamic_netconsole_mutex);
468         return ret;
469 }
470
471 static 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);
493 out_unlock:
494         mutex_unlock(&dynamic_netconsole_mutex);
495         return ret;
496 }
497
498 static 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);
519 out_unlock:
520         mutex_unlock(&dynamic_netconsole_mutex);
521         return ret;
522 }
523
524 static 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
544 static 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);
561 out_unlock:
562         mutex_unlock(&dynamic_netconsole_mutex);
563         return ret;
564 }
565
566 static 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);
583 out_unlock:
584         mutex_unlock(&dynamic_netconsole_mutex);
585         return ret;
586 }
587
588 static 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);
620 out_unlock:
621         mutex_unlock(&dynamic_netconsole_mutex);
622         return ret;
623 }
624
625 static 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);
657 out_unlock:
658         mutex_unlock(&dynamic_netconsole_mutex);
659         return ret;
660 }
661
662 static 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);
683 out_unlock:
684         mutex_unlock(&dynamic_netconsole_mutex);
685         return ret;
686 }
687
688 struct userdatum {
689         struct config_item item;
690         char value[MAX_USERDATA_VALUE_LENGTH];
691 };
692
693 static struct userdatum *to_userdatum(struct config_item *item)
694 {
695         return container_of(item, struct userdatum, item);
696 }
697
698 struct userdata {
699         struct config_group group;
700 };
701
702 static struct userdata *to_userdata(struct config_item *item)
703 {
704         return container_of(to_config_group(item), struct userdata, group);
705 }
706
707 static 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
715 static 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
720 static 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
756 static 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;
778 out_unlock:
779         mutex_unlock(&dynamic_netconsole_mutex);
780         return ret;
781 }
782
783 CONFIGFS_ATTR(userdatum_, value);
784
785 static struct configfs_attribute *userdatum_attrs[] = {
786         &userdatum_attr_value,
787         NULL,
788 };
789
790 static void userdatum_release(struct config_item *item)
791 {
792         kfree(to_userdatum(item));
793 }
794
795 static struct configfs_item_operations userdatum_ops = {
796         .release = userdatum_release,
797 };
798
799 static 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
805 static 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
830 static 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
844 static struct configfs_attribute *userdata_attrs[] = {
845         NULL,
846 };
847
848 static struct configfs_group_operations userdata_ops = {
849         .make_item              = userdatum_make_item,
850         .drop_item              = userdatum_drop,
851 };
852
853 static 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
860 CONFIGFS_ATTR(, enabled);
861 CONFIGFS_ATTR(, extended);
862 CONFIGFS_ATTR(, dev_name);
863 CONFIGFS_ATTR(, local_port);
864 CONFIGFS_ATTR(, remote_port);
865 CONFIGFS_ATTR(, local_ip);
866 CONFIGFS_ATTR(, remote_ip);
867 CONFIGFS_ATTR_RO(, local_mac);
868 CONFIGFS_ATTR(, remote_mac);
869 CONFIGFS_ATTR(, release);
870 CONFIGFS_ATTR_RO(, transmit_errors);
871
872 static 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
891 static void netconsole_target_release(struct config_item *item)
892 {
893         kfree(to_target(item));
894 }
895
896 static struct configfs_item_operations netconsole_target_item_ops = {
897         .release                = netconsole_target_release,
898 };
899
900 static 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
906 static 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
915 static 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
936 static 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
970 static 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
990 static struct configfs_group_operations netconsole_subsys_group_ops = {
991         .make_group     = make_netconsole_target,
992         .drop_item      = drop_netconsole_target,
993 };
994
995 static 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 */
1001 static 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
1010 static 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 */
1023 static 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
1080 done:
1081         return NOTIFY_DONE;
1082 }
1083
1084 static 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  */
1098 static 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
1115 static 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
1145 static 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
1153 static 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
1240 static 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  */
1285 static 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
1304 static 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
1320 static 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 */
1355 static 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
1403 fail:
1404         kfree(nt);
1405         return ERR_PTR(err);
1406 }
1407
1408 /* Cleanup netpoll for given target (from boot/module param) and free it */
1409 static void free_param_target(struct netconsole_target *nt)
1410 {
1411         netpoll_cleanup(&nt->np);
1412         kfree(nt);
1413 }
1414
1415 static struct console netconsole_ext = {
1416         .name   = "netcon_ext",
1417         .flags  = CON_ENABLED | CON_EXTENDED,
1418         .write  = write_ext_msg,
1419 };
1420
1421 static struct console netconsole = {
1422         .name   = "netcon",
1423         .flags  = CON_ENABLED,
1424         .write  = write_msg,
1425 };
1426
1427 static 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
1476 undonotifier:
1477         unregister_netdevice_notifier(&netconsole_netdev_notifier);
1478
1479 fail:
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
1495 static 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  */
1525 late_initcall(init_netconsole);
1526 module_exit(cleanup_netconsole);
This page took 0.150052 seconds and 4 git commands to generate.