bonding: disable arp and enable mii monitoring when bond change to no uses arp mode
[deliverable/linux.git] / drivers / net / bonding / bond_sysfs.c
index 75dc4d0efb340ecb5da41431806785fa9193aaab..abf5e106edc549c053e4d3ffdecce72c4470742e 100644 (file)
@@ -150,14 +150,6 @@ err_no_cmd:
        return -EPERM;
 }
 
-static const void *bonding_namespace(struct class *cls,
-                                    const struct class_attribute *attr)
-{
-       const struct bond_net *bn =
-               container_of(attr, struct bond_net, class_attr_bonding_masters);
-       return bn->net;
-}
-
 /* class attribute for bond_masters file.  This ends up in /sys/class/net */
 static const struct class_attribute class_attr_bonding_masters = {
        .attr = {
@@ -166,7 +158,6 @@ static const struct class_attribute class_attr_bonding_masters = {
        },
        .show = bonding_show_bonds,
        .store = bonding_store_bonds,
-       .namespace = bonding_namespace,
 };
 
 /*
@@ -532,9 +523,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                ret = -EINVAL;
                goto out;
        }
-       if (bond->params.mode == BOND_MODE_ALB ||
-           bond->params.mode == BOND_MODE_TLB) {
-               pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n",
+       if (BOND_NO_USES_ARP(bond->params.mode)) {
+               pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
                        bond->dev->name, bond->dev->name);
                ret = -EINVAL;
                goto out;
@@ -612,15 +602,14 @@ static ssize_t bonding_store_arp_targets(struct device *d,
                return restart_syscall();
 
        targets = bond->params.arp_targets;
-       newtarget = in_aton(buf + 1);
+       if (!in4_pton(buf + 1, -1, (u8 *)&newtarget, -1, NULL) ||
+           IS_IP_TARGET_UNUSABLE_ADDRESS(newtarget)) {
+               pr_err("%s: invalid ARP target %pI4 specified for addition\n",
+                      bond->dev->name, &newtarget);
+               goto out;
+       }
        /* look for adds */
        if (buf[0] == '+') {
-               if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-                       pr_err("%s: invalid ARP target %pI4 specified for addition\n",
-                              bond->dev->name, &newtarget);
-                       goto out;
-               }
-
                if (bond_get_targets_ip(targets, newtarget) != -1) { /* dup */
                        pr_err("%s: ARP target %pI4 is already present\n",
                               bond->dev->name, &newtarget);
@@ -643,12 +632,6 @@ static ssize_t bonding_store_arp_targets(struct device *d,
                targets[ind] = newtarget;
                write_unlock_bh(&bond->lock);
        } else if (buf[0] == '-')       {
-               if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-                       pr_err("%s: invalid ARP target %pI4 specified for removal\n",
-                              bond->dev->name, &newtarget);
-                       goto out;
-               }
-
                ind = bond_get_targets_ip(targets, newtarget);
                if (ind == -1) {
                        pr_err("%s: unable to remove nonexistent ARP target %pI4.\n",
@@ -710,6 +693,8 @@ static ssize_t bonding_store_downdelay(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
        if (!(bond->params.miimon)) {
                pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
                       bond->dev->name);
@@ -743,6 +728,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
        }
 
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
@@ -765,6 +751,8 @@ static ssize_t bonding_store_updelay(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
        if (!(bond->params.miimon)) {
                pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
                       bond->dev->name);
@@ -798,6 +786,7 @@ static ssize_t bonding_store_updelay(struct device *d,
        }
 
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
@@ -1739,7 +1728,8 @@ int bond_create_sysfs(struct bond_net *bn)
        bn->class_attr_bonding_masters = class_attr_bonding_masters;
        sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
 
-       ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
+       ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
+                                         bn->net);
        /*
         * Permit multiple loads of the module by ignoring failures to
         * create the bonding_masters sysfs file.  Bonding devices
@@ -1769,7 +1759,7 @@ int bond_create_sysfs(struct bond_net *bn)
  */
 void bond_destroy_sysfs(struct bond_net *bn)
 {
-       netdev_class_remove_file(&bn->class_attr_bonding_masters);
+       netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
 }
 
 /*
This page took 0.026368 seconds and 5 git commands to generate.