]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/bonding/bond_sysfs.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / bonding / bond_sysfs.c
index bff4f2b84ce03a4b63acb550ac15f4d162b156f8..08f3d396bcd68a669e5cce60a24158dce7c29cdd 100644 (file)
@@ -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,69 +120,60 @@ 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);
                                        res = -EPERM;
-                                       goto out;
+                                       goto out_unlock;
                                }
                                printk(KERN_INFO DRV_NAME
                                        ": %s is being deleted...\n",
                                        bond->dev->name);
                                bond_destroy(bond);
-                               rtnl_unlock();
-                               goto out;
+                               goto out_unlock;
                        }
 
                printk(KERN_ERR DRV_NAME
                        ": unable to delete non-existent bond %s\n", ifname);
                res = -ENODEV;
-               goto out;
+               goto out_unlock;
        }
 
 err_no_cmd:
        printk(KERN_ERR DRV_NAME
                ": no command found in bonding_masters. Use +ifname or -ifname.\n");
-       res = -EPERM;
+       return -EPERM;
+
+out_unlock:
+       up_write(&bonding_rwsem);
+       rtnl_unlock();
 
        /* Always return either count or an error.  If you return 0, you'll
         * 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 */
@@ -271,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) ||
@@ -336,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;
                }
@@ -350,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;
@@ -359,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;
@@ -389,6 +379,8 @@ err_no_cmd:
        ret = -EPERM;
 
 out:
+       up_write(&(bonding_rwsem));
+       rtnl_unlock();
        return ret;
 }
 
@@ -1423,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)
@@ -1447,8 +1437,16 @@ int bond_create_sysfs(void)
         * configure multiple bonding devices.
         */
        if (ret == -EEXIST) {
-               netdev_class = NULL;
-               return 0;
+               /* Is someone being kinky and naming a device bonding_master? */
+               if (__dev_get_by_name(&init_net,
+                                     class_attr_bonding_masters.attr.name))
+                       printk(KERN_ERR
+                              "network device named %s already exists in sysfs",
+                              class_attr_bonding_masters.attr.name);
+               else {
+                       netdev_class = NULL;
+                       return 0;
+               }
        }
 
        return ret;