bonding: Use a per netns implementation of /sys/class/net/bonding_masters.
This fixes a network namespace misfeature that bonding_masters looked at current instead of the remembering the context where in which /sys/class/net/bonding_masters was opened in to see which network namespace to act upon. This removes the need for sysfs to handle tagged directories with untagged members allowing for a conceptually simpler sysfs implementation. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
672d82c18d
commit
4c22400ab6
|
@ -4888,6 +4888,7 @@ static int __net_init bond_net_init(struct net *net)
|
|||
INIT_LIST_HEAD(&bn->dev_list);
|
||||
|
||||
bond_create_proc_dir(bn);
|
||||
bond_create_sysfs(bn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4896,6 +4897,7 @@ static void __net_exit bond_net_exit(struct net *net)
|
|||
{
|
||||
struct bond_net *bn = net_generic(net, bond_net_id);
|
||||
|
||||
bond_destroy_sysfs(bn);
|
||||
bond_destroy_proc_dir(bn);
|
||||
}
|
||||
|
||||
|
@ -4933,10 +4935,6 @@ static int __init bonding_init(void)
|
|||
goto err;
|
||||
}
|
||||
|
||||
res = bond_create_sysfs();
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
register_netdevice_notifier(&bond_netdev_notifier);
|
||||
register_inetaddr_notifier(&bond_inetaddr_notifier);
|
||||
out:
|
||||
|
@ -4954,7 +4952,6 @@ static void __exit bonding_exit(void)
|
|||
unregister_netdevice_notifier(&bond_netdev_notifier);
|
||||
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
|
||||
|
||||
bond_destroy_sysfs();
|
||||
bond_destroy_debugfs();
|
||||
|
||||
rtnl_link_unregister(&bond_link_ops);
|
||||
|
|
|
@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
|
|||
struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct bond_net *bn = net_generic(net, bond_net_id);
|
||||
struct bond_net *bn =
|
||||
container_of(attr, struct bond_net, class_attr_bonding_masters);
|
||||
int res = 0;
|
||||
struct bonding *bond;
|
||||
|
||||
|
@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
|
||||
static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname)
|
||||
{
|
||||
struct bond_net *bn = net_generic(net, bond_net_id);
|
||||
struct bonding *bond;
|
||||
|
||||
list_for_each_entry(bond, &bn->dev_list, bond_list) {
|
||||
|
@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls,
|
|||
struct class_attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct bond_net *bn =
|
||||
container_of(attr, struct bond_net, class_attr_bonding_masters);
|
||||
char command[IFNAMSIZ + 1] = {0, };
|
||||
char *ifname;
|
||||
int rv, res = count;
|
||||
|
@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
|
|||
|
||||
if (command[0] == '+') {
|
||||
pr_info("%s is being created...\n", ifname);
|
||||
rv = bond_create(net, ifname);
|
||||
rv = bond_create(bn->net, ifname);
|
||||
if (rv) {
|
||||
if (rv == -EEXIST)
|
||||
pr_info("%s already exists.\n", ifname);
|
||||
|
@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
|
|||
struct net_device *bond_dev;
|
||||
|
||||
rtnl_lock();
|
||||
bond_dev = bond_get_by_name(net, ifname);
|
||||
bond_dev = bond_get_by_name(bn, ifname);
|
||||
if (bond_dev) {
|
||||
pr_info("%s is being deleted...\n", ifname);
|
||||
unregister_netdevice(bond_dev);
|
||||
|
@ -150,9 +150,24 @@ 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 CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
|
||||
bonding_show_bonds, bonding_store_bonds);
|
||||
static const struct class_attribute class_attr_bonding_masters = {
|
||||
.attr = {
|
||||
.name = "bonding_masters",
|
||||
.mode = S_IWUSR | S_IRUGO,
|
||||
},
|
||||
.show = bonding_show_bonds,
|
||||
.store = bonding_store_bonds,
|
||||
.namespace = bonding_namespace,
|
||||
};
|
||||
|
||||
int bond_create_slave_symlinks(struct net_device *master,
|
||||
struct net_device *slave)
|
||||
|
@ -1655,11 +1670,13 @@ static struct attribute_group bonding_group = {
|
|||
* Initialize sysfs. This sets up the bonding_masters file in
|
||||
* /sys/class/net.
|
||||
*/
|
||||
int bond_create_sysfs(void)
|
||||
int bond_create_sysfs(struct bond_net *bn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = netdev_class_create_file(&class_attr_bonding_masters);
|
||||
bn->class_attr_bonding_masters = class_attr_bonding_masters;
|
||||
|
||||
ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
|
||||
/*
|
||||
* Permit multiple loads of the module by ignoring failures to
|
||||
* create the bonding_masters sysfs file. Bonding devices
|
||||
|
@ -1673,7 +1690,7 @@ int bond_create_sysfs(void)
|
|||
*/
|
||||
if (ret == -EEXIST) {
|
||||
/* Is someone being kinky and naming a device bonding_master? */
|
||||
if (__dev_get_by_name(&init_net,
|
||||
if (__dev_get_by_name(bn->net,
|
||||
class_attr_bonding_masters.attr.name))
|
||||
pr_err("network device named %s already exists in sysfs",
|
||||
class_attr_bonding_masters.attr.name);
|
||||
|
@ -1687,9 +1704,9 @@ int bond_create_sysfs(void)
|
|||
/*
|
||||
* Remove /sys/class/net/bonding_masters.
|
||||
*/
|
||||
void bond_destroy_sysfs(void)
|
||||
void bond_destroy_sysfs(struct bond_net *bn)
|
||||
{
|
||||
netdev_class_remove_file(&class_attr_bonding_masters);
|
||||
netdev_class_remove_file(&bn->class_attr_bonding_masters);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -379,11 +379,13 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
|
|||
return slave->inactive;
|
||||
}
|
||||
|
||||
struct bond_net;
|
||||
|
||||
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
|
||||
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
|
||||
int bond_create(struct net *net, const char *name);
|
||||
int bond_create_sysfs(void);
|
||||
void bond_destroy_sysfs(void);
|
||||
int bond_create_sysfs(struct bond_net *net);
|
||||
void bond_destroy_sysfs(struct bond_net *net);
|
||||
void bond_prepare_sysfs_group(struct bonding *bond);
|
||||
int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
|
||||
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
|
||||
|
@ -409,6 +411,7 @@ struct bond_net {
|
|||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry * proc_dir;
|
||||
#endif
|
||||
struct class_attribute class_attr_bonding_masters;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
|
Loading…
Reference in New Issue