diff options
author | Sven Eckelmann <sven@narfation.org> | 2013-02-11 04:10:22 -0500 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2013-03-27 05:27:31 -0400 |
commit | 37130293fd50918c5498bafafd18735a24229cb9 (patch) | |
tree | 04bd6194d9ffd990f54b55b81fde4ad133c53574 | |
parent | e6a0b495ffee1301c239da49818008e7de3c2ae1 (diff) |
batman-adv: Move soft-interface initialization to ndo_init
The initialization of an net_device object should be done in the
init/constructor function and not from the outside after the register_netdevice
was done to avoid race conditions.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
-rw-r--r-- | net/batman-adv/hard-interface.c | 5 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 169 |
2 files changed, 86 insertions, 88 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 368219e026a9..da000e90f87f 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -563,6 +563,11 @@ static int batadv_hard_if_event(struct notifier_block *this, | |||
563 | struct batadv_hard_iface *primary_if = NULL; | 563 | struct batadv_hard_iface *primary_if = NULL; |
564 | struct batadv_priv *bat_priv; | 564 | struct batadv_priv *bat_priv; |
565 | 565 | ||
566 | if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) { | ||
567 | batadv_sysfs_add_meshif(net_dev); | ||
568 | return NOTIFY_DONE; | ||
569 | } | ||
570 | |||
566 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 571 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
567 | if (!hard_iface && event == NETDEV_REGISTER) | 572 | if (!hard_iface && event == NETDEV_REGISTER) |
568 | hard_iface = batadv_hardif_add_interface(net_dev); | 573 | hard_iface = batadv_hardif_add_interface(net_dev); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index f93ae42abb58..c5cb0a7f8349 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -402,55 +402,6 @@ static void batadv_set_lockdep_class(struct net_device *dev) | |||
402 | } | 402 | } |
403 | 403 | ||
404 | /** | 404 | /** |
405 | * batadv_softif_init - Late stage initialization of soft interface | ||
406 | * @dev: registered network device to modify | ||
407 | * | ||
408 | * Returns error code on failures | ||
409 | */ | ||
410 | static int batadv_softif_init(struct net_device *dev) | ||
411 | { | ||
412 | batadv_set_lockdep_class(dev); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static const struct net_device_ops batadv_netdev_ops = { | ||
418 | .ndo_init = batadv_softif_init, | ||
419 | .ndo_open = batadv_interface_open, | ||
420 | .ndo_stop = batadv_interface_release, | ||
421 | .ndo_get_stats = batadv_interface_stats, | ||
422 | .ndo_set_mac_address = batadv_interface_set_mac_addr, | ||
423 | .ndo_change_mtu = batadv_interface_change_mtu, | ||
424 | .ndo_start_xmit = batadv_interface_tx, | ||
425 | .ndo_validate_addr = eth_validate_addr | ||
426 | }; | ||
427 | |||
428 | static void batadv_interface_setup(struct net_device *dev) | ||
429 | { | ||
430 | struct batadv_priv *priv = netdev_priv(dev); | ||
431 | |||
432 | ether_setup(dev); | ||
433 | |||
434 | dev->netdev_ops = &batadv_netdev_ops; | ||
435 | dev->destructor = free_netdev; | ||
436 | dev->tx_queue_len = 0; | ||
437 | |||
438 | /* can't call min_mtu, because the needed variables | ||
439 | * have not been initialized yet | ||
440 | */ | ||
441 | dev->mtu = ETH_DATA_LEN; | ||
442 | /* reserve more space in the skbuff for our header */ | ||
443 | dev->hard_header_len = BATADV_HEADER_LEN; | ||
444 | |||
445 | /* generate random address */ | ||
446 | eth_hw_addr_random(dev); | ||
447 | |||
448 | SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops); | ||
449 | |||
450 | memset(priv, 0, sizeof(*priv)); | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * batadv_softif_destroy_finish - cleans up the remains of a softif | 405 | * batadv_softif_destroy_finish - cleans up the remains of a softif |
455 | * @work: work queue item | 406 | * @work: work queue item |
456 | * | 407 | * |
@@ -474,21 +425,22 @@ static void batadv_softif_destroy_finish(struct work_struct *work) | |||
474 | rtnl_unlock(); | 425 | rtnl_unlock(); |
475 | } | 426 | } |
476 | 427 | ||
477 | struct net_device *batadv_softif_create(const char *name) | 428 | /** |
429 | * batadv_softif_init_late - late stage initialization of soft interface | ||
430 | * @dev: registered network device to modify | ||
431 | * | ||
432 | * Returns error code on failures | ||
433 | */ | ||
434 | static int batadv_softif_init_late(struct net_device *dev) | ||
478 | { | 435 | { |
479 | struct net_device *soft_iface; | ||
480 | struct batadv_priv *bat_priv; | 436 | struct batadv_priv *bat_priv; |
481 | int ret; | 437 | int ret; |
482 | size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; | 438 | size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM; |
483 | 439 | ||
484 | soft_iface = alloc_netdev(sizeof(*bat_priv), name, | 440 | batadv_set_lockdep_class(dev); |
485 | batadv_interface_setup); | ||
486 | |||
487 | if (!soft_iface) | ||
488 | goto out; | ||
489 | 441 | ||
490 | bat_priv = netdev_priv(soft_iface); | 442 | bat_priv = netdev_priv(dev); |
491 | bat_priv->soft_iface = soft_iface; | 443 | bat_priv->soft_iface = dev; |
492 | INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); | 444 | INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); |
493 | 445 | ||
494 | /* batadv_interface_stats() needs to be available as soon as | 446 | /* batadv_interface_stats() needs to be available as soon as |
@@ -496,14 +448,7 @@ struct net_device *batadv_softif_create(const char *name) | |||
496 | */ | 448 | */ |
497 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); | 449 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); |
498 | if (!bat_priv->bat_counters) | 450 | if (!bat_priv->bat_counters) |
499 | goto free_soft_iface; | 451 | return -ENOMEM; |
500 | |||
501 | ret = register_netdevice(soft_iface); | ||
502 | if (ret < 0) { | ||
503 | pr_err("Unable to register the batman interface '%s': %i\n", | ||
504 | name, ret); | ||
505 | goto free_bat_counters; | ||
506 | } | ||
507 | 452 | ||
508 | atomic_set(&bat_priv->aggregated_ogms, 1); | 453 | atomic_set(&bat_priv->aggregated_ogms, 1); |
509 | atomic_set(&bat_priv->bonding, 0); | 454 | atomic_set(&bat_priv->bonding, 0); |
@@ -541,41 +486,89 @@ struct net_device *batadv_softif_create(const char *name) | |||
541 | bat_priv->primary_if = NULL; | 486 | bat_priv->primary_if = NULL; |
542 | bat_priv->num_ifaces = 0; | 487 | bat_priv->num_ifaces = 0; |
543 | 488 | ||
544 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); | ||
545 | if (ret < 0) | ||
546 | goto unreg_soft_iface; | ||
547 | |||
548 | batadv_nc_init_bat_priv(bat_priv); | 489 | batadv_nc_init_bat_priv(bat_priv); |
549 | 490 | ||
550 | ret = batadv_sysfs_add_meshif(soft_iface); | 491 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); |
551 | if (ret < 0) | 492 | if (ret < 0) |
552 | goto unreg_soft_iface; | 493 | goto free_bat_counters; |
553 | 494 | ||
554 | ret = batadv_debugfs_add_meshif(soft_iface); | 495 | ret = batadv_debugfs_add_meshif(dev); |
555 | if (ret < 0) | 496 | if (ret < 0) |
556 | goto unreg_sysfs; | 497 | goto free_bat_counters; |
557 | 498 | ||
558 | ret = batadv_mesh_init(soft_iface); | 499 | ret = batadv_mesh_init(dev); |
559 | if (ret < 0) | 500 | if (ret < 0) |
560 | goto unreg_debugfs; | 501 | goto unreg_debugfs; |
561 | 502 | ||
562 | return soft_iface; | 503 | return 0; |
563 | 504 | ||
564 | unreg_debugfs: | 505 | unreg_debugfs: |
565 | batadv_debugfs_del_meshif(soft_iface); | 506 | batadv_debugfs_del_meshif(dev); |
566 | unreg_sysfs: | ||
567 | batadv_sysfs_del_meshif(soft_iface); | ||
568 | unreg_soft_iface: | ||
569 | free_percpu(bat_priv->bat_counters); | ||
570 | unregister_netdevice(soft_iface); | ||
571 | return NULL; | ||
572 | |||
573 | free_bat_counters: | 507 | free_bat_counters: |
574 | free_percpu(bat_priv->bat_counters); | 508 | free_percpu(bat_priv->bat_counters); |
575 | free_soft_iface: | 509 | |
576 | free_netdev(soft_iface); | 510 | return ret; |
577 | out: | 511 | } |
578 | return NULL; | 512 | |
513 | static const struct net_device_ops batadv_netdev_ops = { | ||
514 | .ndo_init = batadv_softif_init_late, | ||
515 | .ndo_open = batadv_interface_open, | ||
516 | .ndo_stop = batadv_interface_release, | ||
517 | .ndo_get_stats = batadv_interface_stats, | ||
518 | .ndo_set_mac_address = batadv_interface_set_mac_addr, | ||
519 | .ndo_change_mtu = batadv_interface_change_mtu, | ||
520 | .ndo_start_xmit = batadv_interface_tx, | ||
521 | .ndo_validate_addr = eth_validate_addr | ||
522 | }; | ||
523 | |||
524 | /** | ||
525 | * batadv_softif_init_early - early stage initialization of soft interface | ||
526 | * @dev: registered network device to modify | ||
527 | */ | ||
528 | static void batadv_softif_init_early(struct net_device *dev) | ||
529 | { | ||
530 | struct batadv_priv *priv = netdev_priv(dev); | ||
531 | |||
532 | ether_setup(dev); | ||
533 | |||
534 | dev->netdev_ops = &batadv_netdev_ops; | ||
535 | dev->destructor = free_netdev; | ||
536 | dev->tx_queue_len = 0; | ||
537 | |||
538 | /* can't call min_mtu, because the needed variables | ||
539 | * have not been initialized yet | ||
540 | */ | ||
541 | dev->mtu = ETH_DATA_LEN; | ||
542 | /* reserve more space in the skbuff for our header */ | ||
543 | dev->hard_header_len = BATADV_HEADER_LEN; | ||
544 | |||
545 | /* generate random address */ | ||
546 | eth_hw_addr_random(dev); | ||
547 | |||
548 | SET_ETHTOOL_OPS(dev, &batadv_ethtool_ops); | ||
549 | |||
550 | memset(priv, 0, sizeof(*priv)); | ||
551 | } | ||
552 | |||
553 | struct net_device *batadv_softif_create(const char *name) | ||
554 | { | ||
555 | struct net_device *soft_iface; | ||
556 | int ret; | ||
557 | |||
558 | soft_iface = alloc_netdev(sizeof(struct batadv_priv), name, | ||
559 | batadv_softif_init_early); | ||
560 | if (!soft_iface) | ||
561 | return NULL; | ||
562 | |||
563 | ret = register_netdevice(soft_iface); | ||
564 | if (ret < 0) { | ||
565 | pr_err("Unable to register the batman interface '%s': %i\n", | ||
566 | name, ret); | ||
567 | free_netdev(soft_iface); | ||
568 | return NULL; | ||
569 | } | ||
570 | |||
571 | return soft_iface; | ||
579 | } | 572 | } |
580 | 573 | ||
581 | void batadv_softif_destroy(struct net_device *soft_iface) | 574 | void batadv_softif_destroy(struct net_device *soft_iface) |