bonding: add rtnl lock and remove read lock for bond sysfs
authordingtianhong <dingtianhong@huawei.com>
Tue, 15 Oct 2013 08:28:42 +0000 (16:28 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 17 Oct 2013 19:32:03 +0000 (15:32 -0400)
The bond_for_each_slave() will not be protected by read_lock(),
only protected by rtnl_lock(), so need to replace read_lock()
with rtnl_lock().

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bonding/bond_sysfs.c

index e9249527e7e70970798f7b4ee43fda075a4a4421..03bed0ca935e8bf9476901b1ea7e08c99f4ea4ce 100644 (file)
@@ -179,7 +179,9 @@ static ssize_t bonding_show_slaves(struct device *d,
        struct slave *slave;
        int res = 0;
 
-       read_lock(&bond->lock);
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        bond_for_each_slave(bond, slave, iter) {
                if (res > (PAGE_SIZE - IFNAMSIZ)) {
                        /* not enough space for another interface name */
@@ -190,7 +192,9 @@ static ssize_t bonding_show_slaves(struct device *d,
                }
                res += sprintf(buf + res, "%s ", slave->dev->name);
        }
-       read_unlock(&bond->lock);
+
+       rtnl_unlock();
+
        if (res)
                buf[res-1] = '\n'; /* eat the leftover space */
 
@@ -626,6 +630,9 @@ static ssize_t bonding_store_arp_targets(struct device *d,
        unsigned long *targets_rx;
        int ind, i, j, ret = -EINVAL;
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        targets = bond->params.arp_targets;
        newtarget = in_aton(buf + 1);
        /* look for adds */
@@ -699,6 +706,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
 
        ret = count;
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
@@ -1467,7 +1475,6 @@ static ssize_t bonding_show_queue_id(struct device *d,
        if (!rtnl_trylock())
                return restart_syscall();
 
-       read_lock(&bond->lock);
        bond_for_each_slave(bond, slave, iter) {
                if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
                        /* not enough space for another interface_name:queue_id pair */
@@ -1479,9 +1486,9 @@ static ssize_t bonding_show_queue_id(struct device *d,
                res += sprintf(buf + res, "%s:%d ",
                               slave->dev->name, slave->queue_id);
        }
-       read_unlock(&bond->lock);
        if (res)
                buf[res-1] = '\n'; /* eat the leftover space */
+
        rtnl_unlock();
 
        return res;
@@ -1530,8 +1537,6 @@ static ssize_t bonding_store_queue_id(struct device *d,
        if (!sdev)
                goto err_no_cmd;
 
-       read_lock(&bond->lock);
-
        /* Search for thes slave and check for duplicate qids */
        update_slave = NULL;
        bond_for_each_slave(bond, slave, iter) {
@@ -1542,23 +1547,20 @@ static ssize_t bonding_store_queue_id(struct device *d,
                         */
                        update_slave = slave;
                else if (qid && qid == slave->queue_id) {
-                       goto err_no_cmd_unlock;
+                       goto err_no_cmd;
                }
        }
 
        if (!update_slave)
-               goto err_no_cmd_unlock;
+               goto err_no_cmd;
 
        /* Actually set the qids for the slave */
        update_slave->queue_id = qid;
 
-       read_unlock(&bond->lock);
 out:
        rtnl_unlock();
        return ret;
 
-err_no_cmd_unlock:
-       read_unlock(&bond->lock);
 err_no_cmd:
        pr_info("invalid input for queue_id set for %s.\n",
                bond->dev->name);
@@ -1591,6 +1593,9 @@ static ssize_t bonding_store_slaves_active(struct device *d,
        struct list_head *iter;
        struct slave *slave;
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        if (sscanf(buf, "%d", &new_value) != 1) {
                pr_err("%s: no all_slaves_active value specified.\n",
                       bond->dev->name);
@@ -1610,7 +1615,6 @@ static ssize_t bonding_store_slaves_active(struct device *d,
                goto out;
        }
 
-       read_lock(&bond->lock);
        bond_for_each_slave(bond, slave, iter) {
                if (!bond_is_active_slave(slave)) {
                        if (new_value)
@@ -1619,8 +1623,8 @@ static ssize_t bonding_store_slaves_active(struct device *d,
                                slave->inactive = 1;
                }
        }
-       read_unlock(&bond->lock);
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,