]> err.no Git - linux-2.6/blobdiff - drivers/net/bonding/bond_sysfs.c
Merge branch 'upstream-davem' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / drivers / net / bonding / bond_sysfs.c
index a3f1b4afb40aab7e0d1bb5ce10c63e38fb6743a7..979c2d05ff9c91c19ab7dbee9964cfc608afc299 100644 (file)
@@ -74,7 +74,7 @@ struct rw_semaphore bonding_rwsem;
  * "show" function for the bond_masters attribute.
  * The class parameter is ignored.
  */
-static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
+static ssize_t bonding_show_bonds(struct class *cls, char *buf)
 {
        int res = 0;
        struct bonding *bond;
@@ -86,13 +86,13 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
                        /* not enough space for another interface name */
                        if ((PAGE_SIZE - res) > 10)
                                res = PAGE_SIZE - 10;
-                       res += sprintf(buffer + res, "++more++ ");
+                       res += sprintf(buf + res, "++more++ ");
                        break;
                }
-               res += sprintf(buffer + res, "%s ",
-                              bond->dev->name);
+               res += sprintf(buf + res, "%s ", bond->dev->name);
        }
-       if (res) buffer[res-1] = '\n'; /* eat the leftover space */
+       if (res)
+               buf[res-1] = '\n'; /* eat the leftover space */
        up_read(&(bonding_rwsem));
        return res;
 }
@@ -109,11 +109,10 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
 {
        char command[IFNAMSIZ + 1] = {0, };
        char *ifname;
-       int res = count;
+       int rv, res = count;
        struct bonding *bond;
        struct bonding *nxt;
 
-       down_write(&(bonding_rwsem));
        sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
        ifname = command + 1;
        if ((strlen(command) <= 1) ||
@@ -121,39 +120,28 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
                goto err_no_cmd;
 
        if (command[0] == '+') {
-
-               /* Check to see if the bond already exists. */
-               list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
-                       if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
-                               printk(KERN_ERR DRV_NAME
-                                       ": cannot add bond %s; it already exists\n",
-                                       ifname);
-                               res = -EPERM;
-                               goto out;
-                       }
-
                printk(KERN_INFO DRV_NAME
                        ": %s is being created...\n", ifname);
-               if (bond_create(ifname, &bonding_defaults, &bond)) {
-                       printk(KERN_INFO DRV_NAME
-                       ": %s interface already exists. Bond creation failed.\n",
-                       ifname);
-                       res = -EPERM;
+               rv = bond_create(ifname, &bonding_defaults, &bond);
+               if (rv) {
+                       printk(KERN_INFO DRV_NAME ": Bond creation failed.\n");
+                       res = rv;
                }
                goto out;
        }
 
        if (command[0] == '-') {
+               rtnl_lock();
+               down_write(&bonding_rwsem);
+
                list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
                        if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
-                               rtnl_lock();
                                /* check the ref count on the bond's kobject.
                                 * If it's > expected, then there's a file open,
                                 * and we have to fail.
                                 */
                                if (atomic_read(&bond->dev->dev.kobj.kref.refcount)
                                                        > expected_refcount){
-                                       rtnl_unlock();
                                        printk(KERN_INFO DRV_NAME
                                                ": Unable remove bond %s due to open references.\n",
                                                ifname);
@@ -164,6 +152,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
                                        ": %s is being deleted...\n",
                                        bond->dev->name);
                                bond_destroy(bond);
+                               up_write(&bonding_rwsem);
                                rtnl_unlock();
                                goto out;
                        }
@@ -171,6 +160,8 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
                printk(KERN_ERR DRV_NAME
                        ": unable to delete non-existent bond %s\n", ifname);
                res = -ENODEV;
+               up_write(&bonding_rwsem);
+               rtnl_unlock();
                goto out;
        }
 
@@ -183,7 +174,6 @@ err_no_cmd:
         * get called forever, which is bad.
         */
 out:
-       up_write(&(bonding_rwsem));
        return res;
 }
 /* class attribute for bond_masters file.  This ends up in /sys/class/net */
@@ -240,7 +230,8 @@ static ssize_t bonding_show_slaves(struct device *d,
                res += sprintf(buf + res, "%s ", slave->dev->name);
        }
        read_unlock(&bond->lock);
-       if (res) buf[res-1] = '\n'; /* eat the leftover space */
+       if (res)
+               buf[res-1] = '\n'; /* eat the leftover space */
        return res;
 }
 
@@ -270,6 +261,9 @@ static ssize_t bonding_store_slaves(struct device *d,
 
        /* Note:  We can't hold bond->lock here, as bond_create grabs it. */
 
+       rtnl_lock();
+       down_write(&(bonding_rwsem));
+
        sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
        ifname = command + 1;
        if ((strlen(command) <= 1) ||
@@ -335,12 +329,10 @@ static ssize_t bonding_store_slaves(struct device *d,
                                dev->mtu = bond->dev->mtu;
                        }
                }
-               rtnl_lock();
                res = bond_enslave(bond->dev, dev);
                bond_for_each_slave(bond, slave, i)
                        if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
                                slave->original_mtu = original_mtu;
-               rtnl_unlock();
                if (res) {
                        ret = res;
                }
@@ -349,6 +341,7 @@ static ssize_t bonding_store_slaves(struct device *d,
 
        if (command[0] == '-') {
                dev = NULL;
+               original_mtu = 0;
                bond_for_each_slave(bond, slave, i)
                        if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
                                dev = slave->dev;
@@ -358,12 +351,10 @@ static ssize_t bonding_store_slaves(struct device *d,
                if (dev) {
                        printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
                                bond->dev->name, dev->name);
-                       rtnl_lock();
                        if (bond->setup_by_slave)
                                res = bond_release_and_destroy(bond->dev, dev);
                        else
                                res = bond_release(bond->dev, dev);
-                       rtnl_unlock();
                        if (res) {
                                ret = res;
                                goto out;
@@ -388,6 +379,8 @@ err_no_cmd:
        ret = -EPERM;
 
 out:
+       up_write(&(bonding_rwsem));
+       rtnl_unlock();
        return ret;
 }
 
@@ -422,7 +415,7 @@ static ssize_t bonding_store_mode(struct device *d,
                goto out;
        }
 
-       new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
+       new_value = bond_parse_parm(buf, bond_mode_tbl);
        if (new_value < 0)  {
                printk(KERN_ERR DRV_NAME
                       ": %s: Ignoring invalid mode value %.*s.\n",
@@ -455,20 +448,11 @@ static ssize_t bonding_show_xmit_hash(struct device *d,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       int count;
        struct bonding *bond = to_bond(d);
 
-       if ((bond->params.mode != BOND_MODE_XOR) &&
-           (bond->params.mode != BOND_MODE_8023AD)) {
-               // Not Applicable
-               count = sprintf(buf, "NA\n");
-       } else {
-               count = sprintf(buf, "%s %d\n",
-                       xmit_hashtype_tbl[bond->params.xmit_policy].modename,
-                       bond->params.xmit_policy);
-       }
-
-       return count;
+       return sprintf(buf, "%s %d\n",
+                      xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+                      bond->params.xmit_policy);
 }
 
 static ssize_t bonding_store_xmit_hash(struct device *d,
@@ -486,16 +470,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d,
                goto out;
        }
 
-       if ((bond->params.mode != BOND_MODE_XOR) &&
-           (bond->params.mode != BOND_MODE_8023AD)) {
-               printk(KERN_ERR DRV_NAME
-                      "%s: Transmit hash policy is irrelevant in this mode.\n",
-                      bond->dev->name);
-               ret = -EPERM;
-               goto out;
-       }
-
-       new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
+       new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
        if (new_value < 0)  {
                printk(KERN_ERR DRV_NAME
                       ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
@@ -535,7 +510,7 @@ static ssize_t bonding_store_arp_validate(struct device *d,
        int new_value;
        struct bonding *bond = to_bond(d);
 
-       new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
+       new_value = bond_parse_parm(buf, arp_validate_tbl);
        if (new_value < 0) {
                printk(KERN_ERR DRV_NAME
                       ": %s: Ignoring invalid arp_validate value %s\n",
@@ -709,7 +684,8 @@ static ssize_t bonding_show_arp_targets(struct device *d,
                        res += sprintf(buf + res, "%u.%u.%u.%u ",
                               NIPQUAD(bond->params.arp_targets[i]));
        }
-       if (res) buf[res-1] = '\n'; /* eat the leftover space */
+       if (res)
+               buf[res-1] = '\n'; /* eat the leftover space */
        return res;
 }
 
@@ -957,7 +933,7 @@ static ssize_t bonding_store_lacp(struct device *d,
                goto out;
        }
 
-       new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
+       new_value = bond_parse_parm(buf, bond_lacp_tbl);
 
        if ((new_value == 1) || (new_value == 0)) {
                bond->params.lacp_fast = new_value;
@@ -1079,8 +1055,6 @@ static ssize_t bonding_show_primary(struct device *d,
 
        if (bond->primary_slave)
                count = sprintf(buf, "%s\n", bond->primary_slave->dev->name);
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1093,7 +1067,10 @@ static ssize_t bonding_store_primary(struct device *d,
        struct slave *slave;
        struct bonding *bond = to_bond(d);
 
-       write_lock_bh(&bond->lock);
+       rtnl_lock();
+       read_lock(&bond->lock);
+       write_lock_bh(&bond->curr_slave_lock);
+
        if (!USES_PRIMARY(bond->params.mode)) {
                printk(KERN_INFO DRV_NAME
                       ": %s: Unable to set primary slave; %s is in mode %d\n",
@@ -1127,8 +1104,8 @@ static ssize_t bonding_store_primary(struct device *d,
                }
        }
 out:
-       write_unlock_bh(&bond->lock);
-
+       write_unlock_bh(&bond->curr_slave_lock);
+       read_unlock(&bond->lock);
        rtnl_unlock();
 
        return count;
@@ -1186,7 +1163,7 @@ static ssize_t bonding_show_active_slave(struct device *d,
 {
        struct slave *curr;
        struct bonding *bond = to_bond(d);
-       int count;
+       int count = 0;
 
        read_lock(&bond->curr_slave_lock);
        curr = bond->curr_active_slave;
@@ -1194,8 +1171,6 @@ static ssize_t bonding_show_active_slave(struct device *d,
 
        if (USES_PRIMARY(bond->params.mode) && curr)
                count = sprintf(buf, "%s\n", curr->dev->name);
-       else
-               count = sprintf(buf, "\n");
        return count;
 }
 
@@ -1210,7 +1185,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
        struct bonding *bond = to_bond(d);
 
        rtnl_lock();
-       write_lock_bh(&bond->lock);
+       read_lock(&bond->lock);
+       write_lock_bh(&bond->curr_slave_lock);
 
        if (!USES_PRIMARY(bond->params.mode)) {
                printk(KERN_INFO DRV_NAME
@@ -1267,7 +1243,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
                }
        }
 out:
-       write_unlock_bh(&bond->lock);
+       write_unlock_bh(&bond->curr_slave_lock);
+       read_unlock(&bond->lock);
        rtnl_unlock();
 
        return count;
@@ -1309,8 +1286,6 @@ static ssize_t bonding_show_ad_aggregator(struct device *d,
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.aggregator_id);
        }
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1331,8 +1306,6 @@ static ssize_t bonding_show_ad_num_ports(struct device *d,
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0: ad_info.ports);
        }
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1353,8 +1326,6 @@ static ssize_t bonding_show_ad_actor_key(struct device *d,
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.actor_key);
        }
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1375,8 +1346,6 @@ static ssize_t bonding_show_ad_partner_key(struct device *d,
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.partner_key);
        }
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1401,8 +1370,6 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
                                        print_mac(mac, ad_info.partner_system));
                }
        }
-       else
-               count = sprintf(buf, "\n");
 
        return count;
 }
@@ -1448,8 +1415,6 @@ int bond_create_sysfs(void)
        int ret = 0;
        struct bonding *firstbond;
 
-       init_rwsem(&bonding_rwsem);
-
        /* get the netdev class pointer */
        firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
        if (!firstbond)