diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b0b26036266b..49a198206e3d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1746,7 +1746,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1746 | * has been cleared (if our_slave == old_current), | 1746 | * has been cleared (if our_slave == old_current), |
1747 | * but before a new active slave is selected. | 1747 | * but before a new active slave is selected. |
1748 | */ | 1748 | */ |
1749 | write_unlock_bh(&bond->lock); | ||
1749 | bond_alb_deinit_slave(bond, slave); | 1750 | bond_alb_deinit_slave(bond, slave); |
1751 | write_lock_bh(&bond->lock); | ||
1750 | } | 1752 | } |
1751 | 1753 | ||
1752 | if (oldcurrent == slave) { | 1754 | if (oldcurrent == slave) { |
@@ -1905,6 +1907,12 @@ static int bond_release_all(struct net_device *bond_dev) | |||
1905 | slave_dev = slave->dev; | 1907 | slave_dev = slave->dev; |
1906 | bond_detach_slave(bond, slave); | 1908 | bond_detach_slave(bond, slave); |
1907 | 1909 | ||
1910 | /* now that the slave is detached, unlock and perform | ||
1911 | * all the undo steps that should not be called from | ||
1912 | * within a lock. | ||
1913 | */ | ||
1914 | write_unlock_bh(&bond->lock); | ||
1915 | |||
1908 | if ((bond->params.mode == BOND_MODE_TLB) || | 1916 | if ((bond->params.mode == BOND_MODE_TLB) || |
1909 | (bond->params.mode == BOND_MODE_ALB)) { | 1917 | (bond->params.mode == BOND_MODE_ALB)) { |
1910 | /* must be called only after the slave | 1918 | /* must be called only after the slave |
@@ -1915,12 +1923,6 @@ static int bond_release_all(struct net_device *bond_dev) | |||
1915 | 1923 | ||
1916 | bond_compute_features(bond); | 1924 | bond_compute_features(bond); |
1917 | 1925 | ||
1918 | /* now that the slave is detached, unlock and perform | ||
1919 | * all the undo steps that should not be called from | ||
1920 | * within a lock. | ||
1921 | */ | ||
1922 | write_unlock_bh(&bond->lock); | ||
1923 | |||
1924 | bond_destroy_slave_symlinks(bond_dev, slave_dev); | 1926 | bond_destroy_slave_symlinks(bond_dev, slave_dev); |
1925 | bond_del_vlans_from_slave(bond, slave_dev); | 1927 | bond_del_vlans_from_slave(bond, slave_dev); |
1926 | 1928 | ||
@@ -2384,7 +2386,9 @@ void bond_mii_monitor(struct work_struct *work) | |||
2384 | rtnl_lock(); | 2386 | rtnl_lock(); |
2385 | read_lock(&bond->lock); | 2387 | read_lock(&bond->lock); |
2386 | __bond_mii_monitor(bond, 1); | 2388 | __bond_mii_monitor(bond, 1); |
2387 | rtnl_unlock(); | 2389 | read_unlock(&bond->lock); |
2390 | rtnl_unlock(); /* might sleep, hold no other locks */ | ||
2391 | read_lock(&bond->lock); | ||
2388 | } | 2392 | } |
2389 | 2393 | ||
2390 | delay = ((bond->params.miimon * HZ) / 1000) ? : 1; | 2394 | delay = ((bond->params.miimon * HZ) / 1000) ? : 1; |
@@ -3399,9 +3403,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond | |||
3399 | case NETDEV_CHANGENAME: | 3403 | case NETDEV_CHANGENAME: |
3400 | return bond_event_changename(event_bond); | 3404 | return bond_event_changename(event_bond); |
3401 | case NETDEV_UNREGISTER: | 3405 | case NETDEV_UNREGISTER: |
3402 | /* | 3406 | bond_release_all(event_bond->dev); |
3403 | * TODO: remove a bond from the list? | ||
3404 | */ | ||
3405 | break; | 3407 | break; |
3406 | default: | 3408 | default: |
3407 | break; | 3409 | break; |
@@ -4540,18 +4542,27 @@ static void bond_free_all(void) | |||
4540 | 4542 | ||
4541 | /* | 4543 | /* |
4542 | * Convert string input module parms. Accept either the | 4544 | * Convert string input module parms. Accept either the |
4543 | * number of the mode or its string name. | 4545 | * number of the mode or its string name. A bit complicated because |
4546 | * some mode names are substrings of other names, and calls from sysfs | ||
4547 | * may have whitespace in the name (trailing newlines, for example). | ||
4544 | */ | 4548 | */ |
4545 | int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) | 4549 | int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl) |
4546 | { | 4550 | { |
4547 | int i; | 4551 | int mode = -1, i, rv; |
4552 | char modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, }; | ||
4553 | |||
4554 | rv = sscanf(buf, "%d", &mode); | ||
4555 | if (!rv) { | ||
4556 | rv = sscanf(buf, "%20s", modestr); | ||
4557 | if (!rv) | ||
4558 | return -1; | ||
4559 | } | ||
4548 | 4560 | ||
4549 | for (i = 0; tbl[i].modename; i++) { | 4561 | for (i = 0; tbl[i].modename; i++) { |
4550 | if ((isdigit(*mode_arg) && | 4562 | if (mode == tbl[i].mode) |
4551 | tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) || | 4563 | return tbl[i].mode; |
4552 | (strcmp(mode_arg, tbl[i].modename) == 0)) { | 4564 | if (strcmp(modestr, tbl[i].modename) == 0) |
4553 | return tbl[i].mode; | 4565 | return tbl[i].mode; |
4554 | } | ||
4555 | } | 4566 | } |
4556 | 4567 | ||
4557 | return -1; | 4568 | return -1; |
@@ -4865,9 +4876,22 @@ static struct lock_class_key bonding_netdev_xmit_lock_key; | |||
4865 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond) | 4876 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond) |
4866 | { | 4877 | { |
4867 | struct net_device *bond_dev; | 4878 | struct net_device *bond_dev; |
4879 | struct bonding *bond, *nxt; | ||
4868 | int res; | 4880 | int res; |
4869 | 4881 | ||
4870 | rtnl_lock(); | 4882 | rtnl_lock(); |
4883 | down_write(&bonding_rwsem); | ||
4884 | |||
4885 | /* Check to see if the bond already exists. */ | ||
4886 | list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) | ||
4887 | if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) { | ||
4888 | printk(KERN_ERR DRV_NAME | ||
4889 | ": cannot add bond %s; it already exists\n", | ||
4890 | name); | ||
4891 | res = -EPERM; | ||
4892 | goto out_rtnl; | ||
4893 | } | ||
4894 | |||
4871 | bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", | 4895 | bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", |
4872 | ether_setup); | 4896 | ether_setup); |
4873 | if (!bond_dev) { | 4897 | if (!bond_dev) { |
@@ -4906,10 +4930,12 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond | |||
4906 | 4930 | ||
4907 | netif_carrier_off(bond_dev); | 4931 | netif_carrier_off(bond_dev); |
4908 | 4932 | ||
4933 | up_write(&bonding_rwsem); | ||
4909 | rtnl_unlock(); /* allows sysfs registration of net device */ | 4934 | rtnl_unlock(); /* allows sysfs registration of net device */ |
4910 | res = bond_create_sysfs_entry(bond_dev->priv); | 4935 | res = bond_create_sysfs_entry(bond_dev->priv); |
4911 | if (res < 0) { | 4936 | if (res < 0) { |
4912 | rtnl_lock(); | 4937 | rtnl_lock(); |
4938 | down_write(&bonding_rwsem); | ||
4913 | goto out_bond; | 4939 | goto out_bond; |
4914 | } | 4940 | } |
4915 | 4941 | ||
@@ -4920,6 +4946,7 @@ out_bond: | |||
4920 | out_netdev: | 4946 | out_netdev: |
4921 | free_netdev(bond_dev); | 4947 | free_netdev(bond_dev); |
4922 | out_rtnl: | 4948 | out_rtnl: |
4949 | up_write(&bonding_rwsem); | ||
4923 | rtnl_unlock(); | 4950 | rtnl_unlock(); |
4924 | return res; | 4951 | return res; |
4925 | } | 4952 | } |
@@ -4940,6 +4967,9 @@ static int __init bonding_init(void) | |||
4940 | #ifdef CONFIG_PROC_FS | 4967 | #ifdef CONFIG_PROC_FS |
4941 | bond_create_proc_dir(); | 4968 | bond_create_proc_dir(); |
4942 | #endif | 4969 | #endif |
4970 | |||
4971 | init_rwsem(&bonding_rwsem); | ||
4972 | |||
4943 | for (i = 0; i < max_bonds; i++) { | 4973 | for (i = 0; i < max_bonds; i++) { |
4944 | res = bond_create(NULL, &bonding_defaults, NULL); | 4974 | res = bond_create(NULL, &bonding_defaults, NULL); |
4945 | if (res) | 4975 | if (res) |