1 /* 2 * linux/drivers/net/netconsole.c 3 * 4 * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com> 5 * 6 * This file contains the implementation of an IRQ-safe, crash-safe 7 * kernel console implementation that outputs kernel messages to the 8 * network. 9 * 10 * Modification history: 11 * 12 * 2001-09-17 started by Ingo Molnar. 13 * 2003-08-11 2.6 port by Matt Mackall 14 * simplified options 15 * generic card hooks 16 * works non-modular 17 * 2003-09-07 rewritten with netpoll api 18 */ 19 20 /**************************************************************** 21 * This program is free software; you can redistribute it and/or modify 22 * it under the terms of the GNU General Public License as published by 23 * the Free Software Foundation; either version 2, or (at your option) 24 * any later version. 25 * 26 * This program is distributed in the hope that it will be useful, 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 * GNU General Public License for more details. 30 * 31 * You should have received a copy of the GNU General Public License 32 * along with this program; if not, write to the Free Software 33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 34 * 35 ****************************************************************/ 36 37 #include <linux/mm.h> 38 #include <linux/init.h> 39 #include <linux/module.h> 40 #include <linux/slab.h> 41 #include <linux/console.h> 42 #include <linux/moduleparam.h> 43 #include <linux/kernel.h> 44 #include <linux/string.h> 45 #include <linux/netpoll.h> 46 #include <linux/inet.h> 47 #include <linux/configfs.h> 48 49 MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>"); 50 MODULE_DESCRIPTION("Console driver for network interfaces"); 51 MODULE_LICENSE("GPL"); 52 53 #define MAX_PARAM_LENGTH 256 54 #define MAX_PRINT_CHUNK 1000 55 56 static char config[MAX_PARAM_LENGTH]; 57 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0); 58 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]"); 59 60 static bool oops_only = false; 61 module_param(oops_only, bool, 0600); 62 MODULE_PARM_DESC(oops_only, "Only log oops messages"); 63 64 #ifndef MODULE 65 static int __init option_setup(char *opt) 66 { 67 strlcpy(config, opt, MAX_PARAM_LENGTH); 68 return 1; 69 } 70 __setup("netconsole=", option_setup); 71 #endif /* MODULE */ 72 73 /* Linked list of all configured targets */ 74 static LIST_HEAD(target_list); 75 76 /* This needs to be a spinlock because write_msg() cannot sleep */ 77 static DEFINE_SPINLOCK(target_list_lock); 78 79 /** 80 * struct netconsole_target - Represents a configured netconsole target. 81 * @list: Links this target into the target_list. 82 * @item: Links us into the configfs subsystem hierarchy. 83 * @enabled: On / off knob to enable / disable target. 84 * Visible from userspace (read-write). 85 * We maintain a strict 1:1 correspondence between this and 86 * whether the corresponding netpoll is active or inactive. 87 * Also, other parameters of a target may be modified at 88 * runtime only when it is disabled (enabled == 0). 89 * @np: The netpoll structure for this target. 90 * Contains the other userspace visible parameters: 91 * dev_name (read-write) 92 * local_port (read-write) 93 * remote_port (read-write) 94 * local_ip (read-write) 95 * remote_ip (read-write) 96 * local_mac (read-only) 97 * remote_mac (read-write) 98 */ 99 struct netconsole_target { 100 struct list_head list; 101 #ifdef CONFIG_NETCONSOLE_DYNAMIC 102 struct config_item item; 103 #endif 104 int enabled; 105 struct mutex mutex; 106 struct netpoll np; 107 }; 108 109 #ifdef CONFIG_NETCONSOLE_DYNAMIC 110 111 static struct configfs_subsystem netconsole_subsys; 112 113 static int __init dynamic_netconsole_init(void) 114 { 115 config_group_init(&netconsole_subsys.su_group); 116 mutex_init(&netconsole_subsys.su_mutex); 117 return configfs_register_subsystem(&netconsole_subsys); 118 } 119 120 static void __exit dynamic_netconsole_exit(void) 121 { 122 configfs_unregister_subsystem(&netconsole_subsys); 123 } 124 125 /* 126 * Targets that were created by parsing the boot/module option string 127 * do not exist in the configfs hierarchy (and have NULL names) and will 128 * never go away, so make these a no-op for them. 129 */ 130 static void netconsole_target_get(struct netconsole_target *nt) 131 { 132 if (config_item_name(&nt->item)) 133 config_item_get(&nt->item); 134 } 135 136 static void netconsole_target_put(struct netconsole_target *nt) 137 { 138 if (config_item_name(&nt->item)) 139 config_item_put(&nt->item); 140 } 141 142 #else /* !CONFIG_NETCONSOLE_DYNAMIC */ 143 144 static int __init dynamic_netconsole_init(void) 145 { 146 return 0; 147 } 148 149 static void __exit dynamic_netconsole_exit(void) 150 { 151 } 152 153 /* 154 * No danger of targets going away from under us when dynamic 155 * reconfigurability is off. 156 */ 157 static void netconsole_target_get(struct netconsole_target *nt) 158 { 159 } 160 161 static void netconsole_target_put(struct netconsole_target *nt) 162 { 163 } 164 165 #endif /* CONFIG_NETCONSOLE_DYNAMIC */ 166 167 /* Allocate new target (from boot/module param) and setup netpoll for it */ 168 static struct netconsole_target *alloc_param_target(char *target_config) 169 { 170 int err = -ENOMEM; 171 struct netconsole_target *nt; 172 173 /* 174 * Allocate and initialize with defaults. 175 * Note that these targets get their config_item fields zeroed-out. 176 */ 177 nt = kzalloc(sizeof(*nt), GFP_KERNEL); 178 if (!nt) 179 goto fail; 180 181 nt->np.name = "netconsole"; 182 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ); 183 nt->np.local_port = 6665; 184 nt->np.remote_port = 6666; 185 mutex_init(&nt->mutex); 186 memset(nt->np.remote_mac, 0xff, ETH_ALEN); 187 188 /* Parse parameters and setup netpoll */ 189 err = netpoll_parse_options(&nt->np, target_config); 190 if (err) 191 goto fail; 192 193 err = netpoll_setup(&nt->np); 194 if (err) 195 goto fail; 196 197 nt->enabled = 1; 198 199 return nt; 200 201 fail: 202 kfree(nt); 203 return ERR_PTR(err); 204 } 205 206 /* Cleanup netpoll for given target (from boot/module param) and free it */ 207 static void free_param_target(struct netconsole_target *nt) 208 { 209 netpoll_cleanup(&nt->np); 210 kfree(nt); 211 } 212 213 #ifdef CONFIG_NETCONSOLE_DYNAMIC 214 215 /* 216 * Our subsystem hierarchy is: 217 * 218 * /sys/kernel/config/netconsole/ 219 * | 220 * <target>/ 221 * | enabled 222 * | dev_name 223 * | local_port 224 * | remote_port 225 * | local_ip 226 * | remote_ip 227 * | local_mac 228 * | remote_mac 229 * | 230 * <target>/... 231 */ 232 233 struct netconsole_target_attr { 234 struct configfs_attribute attr; 235 ssize_t (*show)(struct netconsole_target *nt, 236 char *buf); 237 ssize_t (*store)(struct netconsole_target *nt, 238 const char *buf, 239 size_t count); 240 }; 241 242 static struct netconsole_target *to_target(struct config_item *item) 243 { 244 return item ? 245 container_of(item, struct netconsole_target, item) : 246 NULL; 247 } 248 249 /* 250 * Attribute operations for netconsole_target. 251 */ 252 253 static ssize_t show_enabled(struct netconsole_target *nt, char *buf) 254 { 255 return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled); 256 } 257 258 static ssize_t show_dev_name(struct netconsole_target *nt, char *buf) 259 { 260 return snprintf(buf, PAGE_SIZE, "%s\n", nt->np.dev_name); 261 } 262 263 static ssize_t show_local_port(struct netconsole_target *nt, char *buf) 264 { 265 return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.local_port); 266 } 267 268 static ssize_t show_remote_port(struct netconsole_target *nt, char *buf) 269 { 270 return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.remote_port); 271 } 272 273 static ssize_t show_local_ip(struct netconsole_target *nt, char *buf) 274 { 275 if (nt->np.ipv6) 276 return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6); 277 else 278 return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip); 279 } 280 281 static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf) 282 { 283 if (nt->np.ipv6) 284 return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6); 285 else 286 return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip); 287 } 288 289 static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) 290 { 291 struct net_device *dev = nt->np.dev; 292 static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 293 294 return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast); 295 } 296 297 static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf) 298 { 299 return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac); 300 } 301 302 /* 303 * This one is special -- targets created through the configfs interface 304 * are not enabled (and the corresponding netpoll activated) by default. 305 * The user is expected to set the desired parameters first (which 306 * would enable him to dynamically add new netpoll targets for new 307 * network interfaces as and when they come up). 308 */ 309 static ssize_t store_enabled(struct netconsole_target *nt, 310 const char *buf, 311 size_t count) 312 { 313 int enabled; 314 int err; 315 316 err = kstrtoint(buf, 10, &enabled); 317 if (err < 0) 318 return err; 319 if (enabled < 0 || enabled > 1) 320 return -EINVAL; 321 if (enabled == nt->enabled) { 322 printk(KERN_INFO "netconsole: network logging has already %s\n", 323 nt->enabled ? "started" : "stopped"); 324 return -EINVAL; 325 } 326 327 mutex_lock(&nt->mutex); 328 if (enabled) { /* 1 */ 329 330 /* 331 * Skip netpoll_parse_options() -- all the attributes are 332 * already configured via configfs. Just print them out. 333 */ 334 netpoll_print_options(&nt->np); 335 336 err = netpoll_setup(&nt->np); 337 if (err) { 338 mutex_unlock(&nt->mutex); 339 return err; 340 } 341 342 printk(KERN_INFO "netconsole: network logging started\n"); 343 344 } else { /* 0 */ 345 netpoll_cleanup(&nt->np); 346 } 347 348 nt->enabled = enabled; 349 mutex_unlock(&nt->mutex); 350 351 return strnlen(buf, count); 352 } 353 354 static ssize_t store_dev_name(struct netconsole_target *nt, 355 const char *buf, 356 size_t count) 357 { 358 size_t len; 359 360 if (nt->enabled) { 361 printk(KERN_ERR "netconsole: target (%s) is enabled, " 362 "disable to update parameters\n", 363 config_item_name(&nt->item)); 364 return -EINVAL; 365 } 366 367 strlcpy(nt->np.dev_name, buf, IFNAMSIZ); 368 369 /* Get rid of possible trailing newline from echo(1) */ 370 len = strnlen(nt->np.dev_name, IFNAMSIZ); 371 if (nt->np.dev_name[len - 1] == '\n') 372 nt->np.dev_name[len - 1] = '\0'; 373 374 return strnlen(buf, count); 375 } 376 377 static ssize_t store_local_port(struct netconsole_target *nt, 378 const char *buf, 379 size_t count) 380 { 381 int rv; 382 383 if (nt->enabled) { 384 printk(KERN_ERR "netconsole: target (%s) is enabled, " 385 "disable to update parameters\n", 386 config_item_name(&nt->item)); 387 return -EINVAL; 388 } 389 390 rv = kstrtou16(buf, 10, &nt->np.local_port); 391 if (rv < 0) 392 return rv; 393 return strnlen(buf, count); 394 } 395 396 static ssize_t store_remote_port(struct netconsole_target *nt, 397 const char *buf, 398 size_t count) 399 { 400 int rv; 401 402 if (nt->enabled) { 403 printk(KERN_ERR "netconsole: target (%s) is enabled, " 404 "disable to update parameters\n", 405 config_item_name(&nt->item)); 406 return -EINVAL; 407 } 408 409 rv = kstrtou16(buf, 10, &nt->np.remote_port); 410 if (rv < 0) 411 return rv; 412 return strnlen(buf, count); 413 } 414 415 static ssize_t store_local_ip(struct netconsole_target *nt, 416 const char *buf, 417 size_t count) 418 { 419 if (nt->enabled) { 420 printk(KERN_ERR "netconsole: target (%s) is enabled, " 421 "disable to update parameters\n", 422 config_item_name(&nt->item)); 423 return -EINVAL; 424 } 425 426 if (strnchr(buf, count, ':')) { 427 const char *end; 428 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { 429 if (*end && *end != '\n') { 430 printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end); 431 return -EINVAL; 432 } 433 nt->np.ipv6 = true; 434 } else 435 return -EINVAL; 436 } else { 437 if (!nt->np.ipv6) { 438 nt->np.local_ip.ip = in_aton(buf); 439 } else 440 return -EINVAL; 441 } 442 443 return strnlen(buf, count); 444 } 445 446 static ssize_t store_remote_ip(struct netconsole_target *nt, 447 const char *buf, 448 size_t count) 449 { 450 if (nt->enabled) { 451 printk(KERN_ERR "netconsole: target (%s) is enabled, " 452 "disable to update parameters\n", 453 config_item_name(&nt->item)); 454 return -EINVAL; 455 } 456 457 if (strnchr(buf, count, ':')) { 458 const char *end; 459 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { 460 if (*end && *end != '\n') { 461 printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end); 462 return -EINVAL; 463 } 464 nt->np.ipv6 = true; 465 } else 466 return -EINVAL; 467 } else { 468 if (!nt->np.ipv6) { 469 nt->np.remote_ip.ip = in_aton(buf); 470 } else 471 return -EINVAL; 472 } 473 474 return strnlen(buf, count); 475 } 476 477 static ssize_t store_remote_mac(struct netconsole_target *nt, 478 const char *buf, 479 size_t count) 480 { 481 u8 remote_mac[ETH_ALEN]; 482 483 if (nt->enabled) { 484 printk(KERN_ERR "netconsole: target (%s) is enabled, " 485 "disable to update parameters\n", 486 config_item_name(&nt->item)); 487 return -EINVAL; 488 } 489 490 if (!mac_pton(buf, remote_mac)) 491 return -EINVAL; 492 if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') 493 return -EINVAL; 494 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); 495 496 return strnlen(buf, count); 497 } 498 499 /* 500 * Attribute definitions for netconsole_target. 501 */ 502 503 #define NETCONSOLE_TARGET_ATTR_RO(_name) \ 504 static struct netconsole_target_attr netconsole_target_##_name = \ 505 __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL) 506 507 #define NETCONSOLE_TARGET_ATTR_RW(_name) \ 508 static struct netconsole_target_attr netconsole_target_##_name = \ 509 __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name) 510 511 NETCONSOLE_TARGET_ATTR_RW(enabled); 512 NETCONSOLE_TARGET_ATTR_RW(dev_name); 513 NETCONSOLE_TARGET_ATTR_RW(local_port); 514 NETCONSOLE_TARGET_ATTR_RW(remote_port); 515 NETCONSOLE_TARGET_ATTR_RW(local_ip); 516 NETCONSOLE_TARGET_ATTR_RW(remote_ip); 517 NETCONSOLE_TARGET_ATTR_RO(local_mac); 518 NETCONSOLE_TARGET_ATTR_RW(remote_mac); 519 520 static struct configfs_attribute *netconsole_target_attrs[] = { 521 &netconsole_target_enabled.attr, 522 &netconsole_target_dev_name.attr, 523 &netconsole_target_local_port.attr, 524 &netconsole_target_remote_port.attr, 525 &netconsole_target_local_ip.attr, 526 &netconsole_target_remote_ip.attr, 527 &netconsole_target_local_mac.attr, 528 &netconsole_target_remote_mac.attr, 529 NULL, 530 }; 531 532 /* 533 * Item operations and type for netconsole_target. 534 */ 535 536 static void netconsole_target_release(struct config_item *item) 537 { 538 kfree(to_target(item)); 539 } 540 541 static ssize_t netconsole_target_attr_show(struct config_item *item, 542 struct configfs_attribute *attr, 543 char *buf) 544 { 545 ssize_t ret = -EINVAL; 546 struct netconsole_target *nt = to_target(item); 547 struct netconsole_target_attr *na = 548 container_of(attr, struct netconsole_target_attr, attr); 549 550 if (na->show) 551 ret = na->show(nt, buf); 552 553 return ret; 554 } 555 556 static ssize_t netconsole_target_attr_store(struct config_item *item, 557 struct configfs_attribute *attr, 558 const char *buf, 559 size_t count) 560 { 561 ssize_t ret = -EINVAL; 562 struct netconsole_target *nt = to_target(item); 563 struct netconsole_target_attr *na = 564 container_of(attr, struct netconsole_target_attr, attr); 565 566 if (na->store) 567 ret = na->store(nt, buf, count); 568 569 return ret; 570 } 571 572 static struct configfs_item_operations netconsole_target_item_ops = { 573 .release = netconsole_target_release, 574 .show_attribute = netconsole_target_attr_show, 575 .store_attribute = netconsole_target_attr_store, 576 }; 577 578 static struct config_item_type netconsole_target_type = { 579 .ct_attrs = netconsole_target_attrs, 580 .ct_item_ops = &netconsole_target_item_ops, 581 .ct_owner = THIS_MODULE, 582 }; 583 584 /* 585 * Group operations and type for netconsole_subsys. 586 */ 587 588 static struct config_item *make_netconsole_target(struct config_group *group, 589 const char *name) 590 { 591 unsigned long flags; 592 struct netconsole_target *nt; 593 594 /* 595 * Allocate and initialize with defaults. 596 * Target is disabled at creation (enabled == 0). 597 */ 598 nt = kzalloc(sizeof(*nt), GFP_KERNEL); 599 if (!nt) 600 return ERR_PTR(-ENOMEM); 601 602 nt->np.name = "netconsole"; 603 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ); 604 nt->np.local_port = 6665; 605 nt->np.remote_port = 6666; 606 mutex_init(&nt->mutex); 607 memset(nt->np.remote_mac, 0xff, ETH_ALEN); 608 609 /* Initialize the config_item member */ 610 config_item_init_type_name(&nt->item, name, &netconsole_target_type); 611 612 /* Adding, but it is disabled */ 613 spin_lock_irqsave(&target_list_lock, flags); 614 list_add(&nt->list, &target_list); 615 spin_unlock_irqrestore(&target_list_lock, flags); 616 617 return &nt->item; 618 } 619 620 static void drop_netconsole_target(struct config_group *group, 621 struct config_item *item) 622 { 623 unsigned long flags; 624 struct netconsole_target *nt = to_target(item); 625 626 spin_lock_irqsave(&target_list_lock, flags); 627 list_del(&nt->list); 628 spin_unlock_irqrestore(&target_list_lock, flags); 629 630 /* 631 * The target may have never been enabled, or was manually disabled 632 * before being removed so netpoll may have already been cleaned up. 633 */ 634 if (nt->enabled) 635 netpoll_cleanup(&nt->np); 636 637 config_item_put(&nt->item); 638 } 639 640 static struct configfs_group_operations netconsole_subsys_group_ops = { 641 .make_item = make_netconsole_target, 642 .drop_item = drop_netconsole_target, 643 }; 644 645 static struct config_item_type netconsole_subsys_type = { 646 .ct_group_ops = &netconsole_subsys_group_ops, 647 .ct_owner = THIS_MODULE, 648 }; 649 650 /* The netconsole configfs subsystem */ 651 static struct configfs_subsystem netconsole_subsys = { 652 .su_group = { 653 .cg_item = { 654 .ci_namebuf = "netconsole", 655 .ci_type = &netconsole_subsys_type, 656 }, 657 }, 658 }; 659 660 #endif /* CONFIG_NETCONSOLE_DYNAMIC */ 661 662 /* Handle network interface device notifications */ 663 static int netconsole_netdev_event(struct notifier_block *this, 664 unsigned long event, void *ptr) 665 { 666 unsigned long flags; 667 struct netconsole_target *nt; 668 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 669 bool stopped = false; 670 671 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || 672 event == NETDEV_RELEASE || event == NETDEV_JOIN)) 673 goto done; 674 675 spin_lock_irqsave(&target_list_lock, flags); 676 restart: 677 list_for_each_entry(nt, &target_list, list) { 678 netconsole_target_get(nt); 679 if (nt->np.dev == dev) { 680 switch (event) { 681 case NETDEV_CHANGENAME: 682 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); 683 break; 684 case NETDEV_RELEASE: 685 case NETDEV_JOIN: 686 case NETDEV_UNREGISTER: 687 /* rtnl_lock already held 688 * we might sleep in __netpoll_cleanup() 689 */ 690 spin_unlock_irqrestore(&target_list_lock, flags); 691 692 __netpoll_cleanup(&nt->np); 693 694 spin_lock_irqsave(&target_list_lock, flags); 695 dev_put(nt->np.dev); 696 nt->np.dev = NULL; 697 nt->enabled = 0; 698 stopped = true; 699 netconsole_target_put(nt); 700 goto restart; 701 } 702 } 703 netconsole_target_put(nt); 704 } 705 spin_unlock_irqrestore(&target_list_lock, flags); 706 if (stopped) { 707 printk(KERN_INFO "netconsole: network logging stopped on " 708 "interface %s as it ", dev->name); 709 switch (event) { 710 case NETDEV_UNREGISTER: 711 printk(KERN_CONT "unregistered\n"); 712 break; 713 case NETDEV_RELEASE: 714 printk(KERN_CONT "released slaves\n"); 715 break; 716 case NETDEV_JOIN: 717 printk(KERN_CONT "is joining a master device\n"); 718 break; 719 } 720 } 721 722 done: 723 return NOTIFY_DONE; 724 } 725 726 static struct notifier_block netconsole_netdev_notifier = { 727 .notifier_call = netconsole_netdev_event, 728 }; 729 730 static void write_msg(struct console *con, const char *msg, unsigned int len) 731 { 732 int frag, left; 733 unsigned long flags; 734 struct netconsole_target *nt; 735 const char *tmp; 736 737 if (oops_only && !oops_in_progress) 738 return; 739 /* Avoid taking lock and disabling interrupts unnecessarily */ 740 if (list_empty(&target_list)) 741 return; 742 743 spin_lock_irqsave(&target_list_lock, flags); 744 list_for_each_entry(nt, &target_list, list) { 745 netconsole_target_get(nt); 746 if (nt->enabled && netif_running(nt->np.dev)) { 747 /* 748 * We nest this inside the for-each-target loop above 749 * so that we're able to get as much logging out to 750 * at least one target if we die inside here, instead 751 * of unnecessarily keeping all targets in lock-step. 752 */ 753 tmp = msg; 754 for (left = len; left;) { 755 frag = min(left, MAX_PRINT_CHUNK); 756 netpoll_send_udp(&nt->np, tmp, frag); 757 tmp += frag; 758 left -= frag; 759 } 760 } 761 netconsole_target_put(nt); 762 } 763 spin_unlock_irqrestore(&target_list_lock, flags); 764 } 765 766 static struct console netconsole = { 767 .name = "netcon", 768 .flags = CON_ENABLED, 769 .write = write_msg, 770 }; 771 772 static int __init init_netconsole(void) 773 { 774 int err; 775 struct netconsole_target *nt, *tmp; 776 unsigned long flags; 777 char *target_config; 778 char *input = config; 779 780 if (strnlen(input, MAX_PARAM_LENGTH)) { 781 while ((target_config = strsep(&input, ";"))) { 782 nt = alloc_param_target(target_config); 783 if (IS_ERR(nt)) { 784 err = PTR_ERR(nt); 785 goto fail; 786 } 787 /* Dump existing printks when we register */ 788 netconsole.flags |= CON_PRINTBUFFER; 789 790 spin_lock_irqsave(&target_list_lock, flags); 791 list_add(&nt->list, &target_list); 792 spin_unlock_irqrestore(&target_list_lock, flags); 793 } 794 } 795 796 err = register_netdevice_notifier(&netconsole_netdev_notifier); 797 if (err) 798 goto fail; 799 800 err = dynamic_netconsole_init(); 801 if (err) 802 goto undonotifier; 803 804 register_console(&netconsole); 805 printk(KERN_INFO "netconsole: network logging started\n"); 806 807 return err; 808 809 undonotifier: 810 unregister_netdevice_notifier(&netconsole_netdev_notifier); 811 812 fail: 813 printk(KERN_ERR "netconsole: cleaning up\n"); 814 815 /* 816 * Remove all targets and destroy them (only targets created 817 * from the boot/module option exist here). Skipping the list 818 * lock is safe here, and netpoll_cleanup() will sleep. 819 */ 820 list_for_each_entry_safe(nt, tmp, &target_list, list) { 821 list_del(&nt->list); 822 free_param_target(nt); 823 } 824 825 return err; 826 } 827 828 static void __exit cleanup_netconsole(void) 829 { 830 struct netconsole_target *nt, *tmp; 831 832 unregister_console(&netconsole); 833 dynamic_netconsole_exit(); 834 unregister_netdevice_notifier(&netconsole_netdev_notifier); 835 836 /* 837 * Targets created via configfs pin references on our module 838 * and would first be rmdir(2)'ed from userspace. We reach 839 * here only when they are already destroyed, and only those 840 * created from the boot/module option are left, so remove and 841 * destroy them. Skipping the list lock is safe here, and 842 * netpoll_cleanup() will sleep. 843 */ 844 list_for_each_entry_safe(nt, tmp, &target_list, list) { 845 list_del(&nt->list); 846 free_param_target(nt); 847 } 848 } 849 850 /* 851 * Use late_initcall to ensure netconsole is 852 * initialized after network device driver if built-in. 853 * 854 * late_initcall() and module_init() are identical if built as module. 855 */ 856 late_initcall(init_netconsole); 857 module_exit(cleanup_netconsole); 858