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