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 unsigned long flags; 314 int enabled; 315 int err; 316 317 err = kstrtoint(buf, 10, &enabled); 318 if (err < 0) 319 return err; 320 if (enabled < 0 || enabled > 1) 321 return -EINVAL; 322 if (enabled == nt->enabled) { 323 printk(KERN_INFO "netconsole: network logging has already %s\n", 324 nt->enabled ? "started" : "stopped"); 325 return -EINVAL; 326 } 327 328 if (enabled) { /* 1 */ 329 /* 330 * Skip netpoll_parse_options() -- all the attributes are 331 * already configured via configfs. Just print them out. 332 */ 333 netpoll_print_options(&nt->np); 334 335 err = netpoll_setup(&nt->np); 336 if (err) 337 return err; 338 339 printk(KERN_INFO "netconsole: network logging started\n"); 340 } else { /* 0 */ 341 /* We need to disable the netconsole before cleaning it up 342 * otherwise we might end up in write_msg() with 343 * nt->np.dev == NULL and nt->enabled == 1 344 */ 345 spin_lock_irqsave(&target_list_lock, flags); 346 nt->enabled = 0; 347 spin_unlock_irqrestore(&target_list_lock, flags); 348 netpoll_cleanup(&nt->np); 349 } 350 351 nt->enabled = enabled; 352 353 return strnlen(buf, count); 354 } 355 356 static ssize_t store_dev_name(struct netconsole_target *nt, 357 const char *buf, 358 size_t count) 359 { 360 size_t len; 361 362 if (nt->enabled) { 363 printk(KERN_ERR "netconsole: target (%s) is enabled, " 364 "disable to update parameters\n", 365 config_item_name(&nt->item)); 366 return -EINVAL; 367 } 368 369 strlcpy(nt->np.dev_name, buf, IFNAMSIZ); 370 371 /* Get rid of possible trailing newline from echo(1) */ 372 len = strnlen(nt->np.dev_name, IFNAMSIZ); 373 if (nt->np.dev_name[len - 1] == '\n') 374 nt->np.dev_name[len - 1] = '\0'; 375 376 return strnlen(buf, count); 377 } 378 379 static ssize_t store_local_port(struct netconsole_target *nt, 380 const char *buf, 381 size_t count) 382 { 383 int rv; 384 385 if (nt->enabled) { 386 printk(KERN_ERR "netconsole: target (%s) is enabled, " 387 "disable to update parameters\n", 388 config_item_name(&nt->item)); 389 return -EINVAL; 390 } 391 392 rv = kstrtou16(buf, 10, &nt->np.local_port); 393 if (rv < 0) 394 return rv; 395 return strnlen(buf, count); 396 } 397 398 static ssize_t store_remote_port(struct netconsole_target *nt, 399 const char *buf, 400 size_t count) 401 { 402 int rv; 403 404 if (nt->enabled) { 405 printk(KERN_ERR "netconsole: target (%s) is enabled, " 406 "disable to update parameters\n", 407 config_item_name(&nt->item)); 408 return -EINVAL; 409 } 410 411 rv = kstrtou16(buf, 10, &nt->np.remote_port); 412 if (rv < 0) 413 return rv; 414 return strnlen(buf, count); 415 } 416 417 static ssize_t store_local_ip(struct netconsole_target *nt, 418 const char *buf, 419 size_t count) 420 { 421 if (nt->enabled) { 422 printk(KERN_ERR "netconsole: target (%s) is enabled, " 423 "disable to update parameters\n", 424 config_item_name(&nt->item)); 425 return -EINVAL; 426 } 427 428 if (strnchr(buf, count, ':')) { 429 const char *end; 430 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { 431 if (*end && *end != '\n') { 432 printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end); 433 return -EINVAL; 434 } 435 nt->np.ipv6 = true; 436 } else 437 return -EINVAL; 438 } else { 439 if (!nt->np.ipv6) { 440 nt->np.local_ip.ip = in_aton(buf); 441 } else 442 return -EINVAL; 443 } 444 445 return strnlen(buf, count); 446 } 447 448 static ssize_t store_remote_ip(struct netconsole_target *nt, 449 const char *buf, 450 size_t count) 451 { 452 if (nt->enabled) { 453 printk(KERN_ERR "netconsole: target (%s) is enabled, " 454 "disable to update parameters\n", 455 config_item_name(&nt->item)); 456 return -EINVAL; 457 } 458 459 if (strnchr(buf, count, ':')) { 460 const char *end; 461 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { 462 if (*end && *end != '\n') { 463 printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end); 464 return -EINVAL; 465 } 466 nt->np.ipv6 = true; 467 } else 468 return -EINVAL; 469 } else { 470 if (!nt->np.ipv6) { 471 nt->np.remote_ip.ip = in_aton(buf); 472 } else 473 return -EINVAL; 474 } 475 476 return strnlen(buf, count); 477 } 478 479 static ssize_t store_remote_mac(struct netconsole_target *nt, 480 const char *buf, 481 size_t count) 482 { 483 u8 remote_mac[ETH_ALEN]; 484 485 if (nt->enabled) { 486 printk(KERN_ERR "netconsole: target (%s) is enabled, " 487 "disable to update parameters\n", 488 config_item_name(&nt->item)); 489 return -EINVAL; 490 } 491 492 if (!mac_pton(buf, remote_mac)) 493 return -EINVAL; 494 if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') 495 return -EINVAL; 496 memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); 497 498 return strnlen(buf, count); 499 } 500 501 /* 502 * Attribute definitions for netconsole_target. 503 */ 504 505 #define NETCONSOLE_TARGET_ATTR_RO(_name) \ 506 static struct netconsole_target_attr netconsole_target_##_name = \ 507 __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL) 508 509 #define NETCONSOLE_TARGET_ATTR_RW(_name) \ 510 static struct netconsole_target_attr netconsole_target_##_name = \ 511 __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name) 512 513 NETCONSOLE_TARGET_ATTR_RW(enabled); 514 NETCONSOLE_TARGET_ATTR_RW(dev_name); 515 NETCONSOLE_TARGET_ATTR_RW(local_port); 516 NETCONSOLE_TARGET_ATTR_RW(remote_port); 517 NETCONSOLE_TARGET_ATTR_RW(local_ip); 518 NETCONSOLE_TARGET_ATTR_RW(remote_ip); 519 NETCONSOLE_TARGET_ATTR_RO(local_mac); 520 NETCONSOLE_TARGET_ATTR_RW(remote_mac); 521 522 static struct configfs_attribute *netconsole_target_attrs[] = { 523 &netconsole_target_enabled.attr, 524 &netconsole_target_dev_name.attr, 525 &netconsole_target_local_port.attr, 526 &netconsole_target_remote_port.attr, 527 &netconsole_target_local_ip.attr, 528 &netconsole_target_remote_ip.attr, 529 &netconsole_target_local_mac.attr, 530 &netconsole_target_remote_mac.attr, 531 NULL, 532 }; 533 534 /* 535 * Item operations and type for netconsole_target. 536 */ 537 538 static void netconsole_target_release(struct config_item *item) 539 { 540 kfree(to_target(item)); 541 } 542 543 static ssize_t netconsole_target_attr_show(struct config_item *item, 544 struct configfs_attribute *attr, 545 char *buf) 546 { 547 ssize_t ret = -EINVAL; 548 struct netconsole_target *nt = to_target(item); 549 struct netconsole_target_attr *na = 550 container_of(attr, struct netconsole_target_attr, attr); 551 552 if (na->show) 553 ret = na->show(nt, buf); 554 555 return ret; 556 } 557 558 static ssize_t netconsole_target_attr_store(struct config_item *item, 559 struct configfs_attribute *attr, 560 const char *buf, 561 size_t count) 562 { 563 ssize_t ret = -EINVAL; 564 struct netconsole_target *nt = to_target(item); 565 struct netconsole_target_attr *na = 566 container_of(attr, struct netconsole_target_attr, attr); 567 568 mutex_lock(&nt->mutex); 569 if (na->store) 570 ret = na->store(nt, buf, count); 571 mutex_unlock(&nt->mutex); 572 573 return ret; 574 } 575 576 static struct configfs_item_operations netconsole_target_item_ops = { 577 .release = netconsole_target_release, 578 .show_attribute = netconsole_target_attr_show, 579 .store_attribute = netconsole_target_attr_store, 580 }; 581 582 static struct config_item_type netconsole_target_type = { 583 .ct_attrs = netconsole_target_attrs, 584 .ct_item_ops = &netconsole_target_item_ops, 585 .ct_owner = THIS_MODULE, 586 }; 587 588 /* 589 * Group operations and type for netconsole_subsys. 590 */ 591 592 static struct config_item *make_netconsole_target(struct config_group *group, 593 const char *name) 594 { 595 unsigned long flags; 596 struct netconsole_target *nt; 597 598 /* 599 * Allocate and initialize with defaults. 600 * Target is disabled at creation (enabled == 0). 601 */ 602 nt = kzalloc(sizeof(*nt), GFP_KERNEL); 603 if (!nt) 604 return ERR_PTR(-ENOMEM); 605 606 nt->np.name = "netconsole"; 607 strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ); 608 nt->np.local_port = 6665; 609 nt->np.remote_port = 6666; 610 mutex_init(&nt->mutex); 611 memset(nt->np.remote_mac, 0xff, ETH_ALEN); 612 613 /* Initialize the config_item member */ 614 config_item_init_type_name(&nt->item, name, &netconsole_target_type); 615 616 /* Adding, but it is disabled */ 617 spin_lock_irqsave(&target_list_lock, flags); 618 list_add(&nt->list, &target_list); 619 spin_unlock_irqrestore(&target_list_lock, flags); 620 621 return &nt->item; 622 } 623 624 static void drop_netconsole_target(struct config_group *group, 625 struct config_item *item) 626 { 627 unsigned long flags; 628 struct netconsole_target *nt = to_target(item); 629 630 spin_lock_irqsave(&target_list_lock, flags); 631 list_del(&nt->list); 632 spin_unlock_irqrestore(&target_list_lock, flags); 633 634 /* 635 * The target may have never been enabled, or was manually disabled 636 * before being removed so netpoll may have already been cleaned up. 637 */ 638 if (nt->enabled) 639 netpoll_cleanup(&nt->np); 640 641 config_item_put(&nt->item); 642 } 643 644 static struct configfs_group_operations netconsole_subsys_group_ops = { 645 .make_item = make_netconsole_target, 646 .drop_item = drop_netconsole_target, 647 }; 648 649 static struct config_item_type netconsole_subsys_type = { 650 .ct_group_ops = &netconsole_subsys_group_ops, 651 .ct_owner = THIS_MODULE, 652 }; 653 654 /* The netconsole configfs subsystem */ 655 static struct configfs_subsystem netconsole_subsys = { 656 .su_group = { 657 .cg_item = { 658 .ci_namebuf = "netconsole", 659 .ci_type = &netconsole_subsys_type, 660 }, 661 }, 662 }; 663 664 #endif /* CONFIG_NETCONSOLE_DYNAMIC */ 665 666 /* Handle network interface device notifications */ 667 static int netconsole_netdev_event(struct notifier_block *this, 668 unsigned long event, void *ptr) 669 { 670 unsigned long flags; 671 struct netconsole_target *nt; 672 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 673 bool stopped = false; 674 675 if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || 676 event == NETDEV_RELEASE || event == NETDEV_JOIN)) 677 goto done; 678 679 spin_lock_irqsave(&target_list_lock, flags); 680 restart: 681 list_for_each_entry(nt, &target_list, list) { 682 netconsole_target_get(nt); 683 if (nt->np.dev == dev) { 684 switch (event) { 685 case NETDEV_CHANGENAME: 686 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); 687 break; 688 case NETDEV_RELEASE: 689 case NETDEV_JOIN: 690 case NETDEV_UNREGISTER: 691 /* rtnl_lock already held 692 * we might sleep in __netpoll_cleanup() 693 */ 694 spin_unlock_irqrestore(&target_list_lock, flags); 695 696 __netpoll_cleanup(&nt->np); 697 698 spin_lock_irqsave(&target_list_lock, flags); 699 dev_put(nt->np.dev); 700 nt->np.dev = NULL; 701 nt->enabled = 0; 702 stopped = true; 703 netconsole_target_put(nt); 704 goto restart; 705 } 706 } 707 netconsole_target_put(nt); 708 } 709 spin_unlock_irqrestore(&target_list_lock, flags); 710 if (stopped) { 711 printk(KERN_INFO "netconsole: network logging stopped on " 712 "interface %s as it ", dev->name); 713 switch (event) { 714 case NETDEV_UNREGISTER: 715 printk(KERN_CONT "unregistered\n"); 716 break; 717 case NETDEV_RELEASE: 718 printk(KERN_CONT "released slaves\n"); 719 break; 720 case NETDEV_JOIN: 721 printk(KERN_CONT "is joining a master device\n"); 722 break; 723 } 724 } 725 726 done: 727 return NOTIFY_DONE; 728 } 729 730 static struct notifier_block netconsole_netdev_notifier = { 731 .notifier_call = netconsole_netdev_event, 732 }; 733 734 static void write_msg(struct console *con, const char *msg, unsigned int len) 735 { 736 int frag, left; 737 unsigned long flags; 738 struct netconsole_target *nt; 739 const char *tmp; 740 741 if (oops_only && !oops_in_progress) 742 return; 743 /* Avoid taking lock and disabling interrupts unnecessarily */ 744 if (list_empty(&target_list)) 745 return; 746 747 spin_lock_irqsave(&target_list_lock, flags); 748 list_for_each_entry(nt, &target_list, list) { 749 netconsole_target_get(nt); 750 if (nt->enabled && netif_running(nt->np.dev)) { 751 /* 752 * We nest this inside the for-each-target loop above 753 * so that we're able to get as much logging out to 754 * at least one target if we die inside here, instead 755 * of unnecessarily keeping all targets in lock-step. 756 */ 757 tmp = msg; 758 for (left = len; left;) { 759 frag = min(left, MAX_PRINT_CHUNK); 760 netpoll_send_udp(&nt->np, tmp, frag); 761 tmp += frag; 762 left -= frag; 763 } 764 } 765 netconsole_target_put(nt); 766 } 767 spin_unlock_irqrestore(&target_list_lock, flags); 768 } 769 770 static struct console netconsole = { 771 .name = "netcon", 772 .flags = CON_ENABLED, 773 .write = write_msg, 774 }; 775 776 static int __init init_netconsole(void) 777 { 778 int err; 779 struct netconsole_target *nt, *tmp; 780 unsigned long flags; 781 char *target_config; 782 char *input = config; 783 784 if (strnlen(input, MAX_PARAM_LENGTH)) { 785 while ((target_config = strsep(&input, ";"))) { 786 nt = alloc_param_target(target_config); 787 if (IS_ERR(nt)) { 788 err = PTR_ERR(nt); 789 goto fail; 790 } 791 /* Dump existing printks when we register */ 792 netconsole.flags |= CON_PRINTBUFFER; 793 794 spin_lock_irqsave(&target_list_lock, flags); 795 list_add(&nt->list, &target_list); 796 spin_unlock_irqrestore(&target_list_lock, flags); 797 } 798 } 799 800 err = register_netdevice_notifier(&netconsole_netdev_notifier); 801 if (err) 802 goto fail; 803 804 err = dynamic_netconsole_init(); 805 if (err) 806 goto undonotifier; 807 808 register_console(&netconsole); 809 printk(KERN_INFO "netconsole: network logging started\n"); 810 811 return err; 812 813 undonotifier: 814 unregister_netdevice_notifier(&netconsole_netdev_notifier); 815 816 fail: 817 printk(KERN_ERR "netconsole: cleaning up\n"); 818 819 /* 820 * Remove all targets and destroy them (only targets created 821 * from the boot/module option exist here). Skipping the list 822 * lock is safe here, and netpoll_cleanup() will sleep. 823 */ 824 list_for_each_entry_safe(nt, tmp, &target_list, list) { 825 list_del(&nt->list); 826 free_param_target(nt); 827 } 828 829 return err; 830 } 831 832 static void __exit cleanup_netconsole(void) 833 { 834 struct netconsole_target *nt, *tmp; 835 836 unregister_console(&netconsole); 837 dynamic_netconsole_exit(); 838 unregister_netdevice_notifier(&netconsole_netdev_notifier); 839 840 /* 841 * Targets created via configfs pin references on our module 842 * and would first be rmdir(2)'ed from userspace. We reach 843 * here only when they are already destroyed, and only those 844 * created from the boot/module option are left, so remove and 845 * destroy them. Skipping the list lock is safe here, and 846 * netpoll_cleanup() will sleep. 847 */ 848 list_for_each_entry_safe(nt, tmp, &target_list, list) { 849 list_del(&nt->list); 850 free_param_target(nt); 851 } 852 } 853 854 /* 855 * Use late_initcall to ensure netconsole is 856 * initialized after network device driver if built-in. 857 * 858 * late_initcall() and module_init() are identical if built as module. 859 */ 860 late_initcall(init_netconsole); 861 module_exit(cleanup_netconsole); 862