Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-block.git] / drivers / net / bonding / bond_sysfs.c
index 8762a27a2a185dd37d47db0263fcc019f471b1da..4e00b4f836411eabb4fcc41959c5415bc9bcb13d 100644 (file)
@@ -36,6 +36,8 @@
 #include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <linux/nsproxy.h>
 
 #include "bonding.h"
 
  */
 static ssize_t bonding_show_bonds(struct class *cls, char *buf)
 {
+       struct net *net = current->nsproxy->net_ns;
+       struct bond_net *bn = net_generic(net, bond_net_id);
        int res = 0;
        struct bonding *bond;
 
        rtnl_lock();
 
-       list_for_each_entry(bond, &bond_dev_list, bond_list) {
+       list_for_each_entry(bond, &bn->dev_list, bond_list) {
                if (res > (PAGE_SIZE - IFNAMSIZ)) {
                        /* not enough space for another interface name */
                        if ((PAGE_SIZE - res) > 10)
@@ -70,11 +74,12 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf)
        return res;
 }
 
-static struct net_device *bond_get_by_name(const char *ifname)
+static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
 {
+       struct bond_net *bn = net_generic(net, bond_net_id);
        struct bonding *bond;
 
-       list_for_each_entry(bond, &bond_dev_list, bond_list) {
+       list_for_each_entry(bond, &bn->dev_list, bond_list) {
                if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
                        return bond->dev;
        }
@@ -92,6 +97,7 @@ static struct net_device *bond_get_by_name(const char *ifname)
 static ssize_t bonding_store_bonds(struct class *cls,
                                   const char *buffer, size_t count)
 {
+       struct net *net = current->nsproxy->net_ns;
        char command[IFNAMSIZ + 1] = {0, };
        char *ifname;
        int rv, res = count;
@@ -105,7 +111,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
        if (command[0] == '+') {
                pr_info(DRV_NAME
                        ": %s is being created...\n", ifname);
-               rv = bond_create(ifname);
+               rv = bond_create(net, ifname);
                if (rv) {
                        pr_info(DRV_NAME ": Bond creation failed.\n");
                        res = rv;
@@ -114,7 +120,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
                struct net_device *bond_dev;
 
                rtnl_lock();
-               bond_dev = bond_get_by_name(ifname);
+               bond_dev = bond_get_by_name(net, ifname);
                if (bond_dev) {
                        pr_info(DRV_NAME ": %s is being deleted...\n",
                                ifname);
@@ -239,8 +245,7 @@ static ssize_t bonding_store_slaves(struct device *d,
                /* Got a slave name in ifname.  Is it already in the list? */
                found = 0;
 
-               /* FIXME: get netns from sysfs object */
-               dev = __dev_get_by_name(&init_net, ifname);
+               dev = __dev_get_by_name(dev_net(bond->dev), ifname);
                if (!dev) {
                        pr_info(DRV_NAME
                               ": %s: Interface %s does not exist!\n",
@@ -1213,6 +1218,58 @@ out:
 static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
                   bonding_show_primary, bonding_store_primary);
 
+/*
+ * Show and set the primary_reselect flag.
+ */
+static ssize_t bonding_show_primary_reselect(struct device *d,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       struct bonding *bond = to_bond(d);
+
+       return sprintf(buf, "%s %d\n",
+                      pri_reselect_tbl[bond->params.primary_reselect].modename,
+                      bond->params.primary_reselect);
+}
+
+static ssize_t bonding_store_primary_reselect(struct device *d,
+                                             struct device_attribute *attr,
+                                             const char *buf, size_t count)
+{
+       int new_value, ret = count;
+       struct bonding *bond = to_bond(d);
+
+       if (!rtnl_trylock())
+               return restart_syscall();
+
+       new_value = bond_parse_parm(buf, pri_reselect_tbl);
+       if (new_value < 0)  {
+               pr_err(DRV_NAME
+                      ": %s: Ignoring invalid primary_reselect value %.*s.\n",
+                      bond->dev->name,
+                      (int) strlen(buf) - 1, buf);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       bond->params.primary_reselect = new_value;
+       pr_info(DRV_NAME ": %s: setting primary_reselect to %s (%d).\n",
+               bond->dev->name, pri_reselect_tbl[new_value].modename,
+               new_value);
+
+       read_lock(&bond->lock);
+       write_lock_bh(&bond->curr_slave_lock);
+       bond_select_active_slave(bond);
+       write_unlock_bh(&bond->curr_slave_lock);
+       read_unlock(&bond->lock);
+out:
+       rtnl_unlock();
+       return ret;
+}
+static DEVICE_ATTR(primary_reselect, S_IRUGO | S_IWUSR,
+                  bonding_show_primary_reselect,
+                  bonding_store_primary_reselect);
+
 /*
  * Show and set the use_carrier flag.
  */
@@ -1502,6 +1559,7 @@ static struct attribute *per_bond_attrs[] = {
        &dev_attr_num_unsol_na.attr,
        &dev_attr_miimon.attr,
        &dev_attr_primary.attr,
+       &dev_attr_primary_reselect.attr,
        &dev_attr_use_carrier.attr,
        &dev_attr_active_slave.attr,
        &dev_attr_mii_status.attr,
@@ -1564,24 +1622,8 @@ void bond_destroy_sysfs(void)
  * Initialize sysfs for each bond.  This sets up and registers
  * the 'bondctl' directory for each individual bond under /sys/class/net.
  */
-int bond_create_sysfs_entry(struct bonding *bond)
+void bond_prepare_sysfs_group(struct bonding *bond)
 {
-       struct net_device *dev = bond->dev;
-       int err;
-
-       err = sysfs_create_group(&(dev->dev.kobj), &bonding_group);
-       if (err)
-               pr_emerg("eek! didn't create group!\n");
-
-       return err;
-}
-/*
- * Remove sysfs entries for each bond.
- */
-void bond_destroy_sysfs_entry(struct bonding *bond)
-{
-       struct net_device *dev = bond->dev;
-
-       sysfs_remove_group(&(dev->dev.kobj), &bonding_group);
+       bond->dev->sysfs_groups[0] = &bonding_group;
 }