diff options
Diffstat (limited to 'drivers/net/bonding/bond_sysfs.c')
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 8762a27a2a1..4e00b4f8364 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -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" @@ -48,12 +50,14 @@ */ 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", @@ -1214,6 +1219,58 @@ 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. */ static ssize_t bonding_show_carrier(struct device *d, @@ -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; } |