Commit 4c22400a authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

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: default avatarEric W. Biederman <ebiederm@xmission.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 672d82c1
...@@ -4888,6 +4888,7 @@ static int __net_init bond_net_init(struct net *net) ...@@ -4888,6 +4888,7 @@ static int __net_init bond_net_init(struct net *net)
INIT_LIST_HEAD(&bn->dev_list); INIT_LIST_HEAD(&bn->dev_list);
bond_create_proc_dir(bn); bond_create_proc_dir(bn);
bond_create_sysfs(bn);
return 0; return 0;
} }
...@@ -4896,6 +4897,7 @@ static void __net_exit bond_net_exit(struct net *net) ...@@ -4896,6 +4897,7 @@ static void __net_exit bond_net_exit(struct net *net)
{ {
struct bond_net *bn = net_generic(net, bond_net_id); struct bond_net *bn = net_generic(net, bond_net_id);
bond_destroy_sysfs(bn);
bond_destroy_proc_dir(bn); bond_destroy_proc_dir(bn);
} }
...@@ -4933,10 +4935,6 @@ static int __init bonding_init(void) ...@@ -4933,10 +4935,6 @@ static int __init bonding_init(void)
goto err; goto err;
} }
res = bond_create_sysfs();
if (res)
goto err;
register_netdevice_notifier(&bond_netdev_notifier); register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier); register_inetaddr_notifier(&bond_inetaddr_notifier);
out: out:
...@@ -4954,7 +4952,6 @@ static void __exit bonding_exit(void) ...@@ -4954,7 +4952,6 @@ static void __exit bonding_exit(void)
unregister_netdevice_notifier(&bond_netdev_notifier); unregister_netdevice_notifier(&bond_netdev_notifier);
unregister_inetaddr_notifier(&bond_inetaddr_notifier); unregister_inetaddr_notifier(&bond_inetaddr_notifier);
bond_destroy_sysfs();
bond_destroy_debugfs(); bond_destroy_debugfs();
rtnl_link_unregister(&bond_link_ops); rtnl_link_unregister(&bond_link_ops);
......
...@@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls, ...@@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
struct class_attribute *attr, struct class_attribute *attr,
char *buf) char *buf)
{ {
struct net *net = current->nsproxy->net_ns; struct bond_net *bn =
struct bond_net *bn = net_generic(net, bond_net_id); container_of(attr, struct bond_net, class_attr_bonding_masters);
int res = 0; int res = 0;
struct bonding *bond; struct bonding *bond;
...@@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls, ...@@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls,
return res; 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; struct bonding *bond;
list_for_each_entry(bond, &bn->dev_list, bond_list) { list_for_each_entry(bond, &bn->dev_list, bond_list) {
...@@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct class_attribute *attr, struct class_attribute *attr,
const char *buffer, size_t count) 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 command[IFNAMSIZ + 1] = {0, };
char *ifname; char *ifname;
int rv, res = count; int rv, res = count;
...@@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
if (command[0] == '+') { if (command[0] == '+') {
pr_info("%s is being created...\n", ifname); pr_info("%s is being created...\n", ifname);
rv = bond_create(net, ifname); rv = bond_create(bn->net, ifname);
if (rv) { if (rv) {
if (rv == -EEXIST) if (rv == -EEXIST)
pr_info("%s already exists.\n", ifname); pr_info("%s already exists.\n", ifname);
...@@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls,
struct net_device *bond_dev; struct net_device *bond_dev;
rtnl_lock(); rtnl_lock();
bond_dev = bond_get_by_name(net, ifname); bond_dev = bond_get_by_name(bn, ifname);
if (bond_dev) { if (bond_dev) {
pr_info("%s is being deleted...\n", ifname); pr_info("%s is being deleted...\n", ifname);
unregister_netdevice(bond_dev); unregister_netdevice(bond_dev);
...@@ -150,9 +150,24 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -150,9 +150,24 @@ static ssize_t bonding_store_bonds(struct class *cls,
return -EPERM; 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 */ /* class attribute for bond_masters file. This ends up in /sys/class/net */
static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, static const struct class_attribute class_attr_bonding_masters = {
bonding_show_bonds, bonding_store_bonds); .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, int bond_create_slave_symlinks(struct net_device *master,
struct net_device *slave) struct net_device *slave)
...@@ -1655,11 +1670,13 @@ static struct attribute_group bonding_group = { ...@@ -1655,11 +1670,13 @@ static struct attribute_group bonding_group = {
* Initialize sysfs. This sets up the bonding_masters file in * Initialize sysfs. This sets up the bonding_masters file in
* /sys/class/net. * /sys/class/net.
*/ */
int bond_create_sysfs(void) int bond_create_sysfs(struct bond_net *bn)
{ {
int ret; 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 * Permit multiple loads of the module by ignoring failures to
* create the bonding_masters sysfs file. Bonding devices * create the bonding_masters sysfs file. Bonding devices
...@@ -1673,7 +1690,7 @@ int bond_create_sysfs(void) ...@@ -1673,7 +1690,7 @@ int bond_create_sysfs(void)
*/ */
if (ret == -EEXIST) { if (ret == -EEXIST) {
/* Is someone being kinky and naming a device bonding_master? */ /* 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)) class_attr_bonding_masters.attr.name))
pr_err("network device named %s already exists in sysfs", pr_err("network device named %s already exists in sysfs",
class_attr_bonding_masters.attr.name); class_attr_bonding_masters.attr.name);
...@@ -1687,9 +1704,9 @@ int bond_create_sysfs(void) ...@@ -1687,9 +1704,9 @@ int bond_create_sysfs(void)
/* /*
* Remove /sys/class/net/bonding_masters. * 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) ...@@ -379,11 +379,13 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
return slave->inactive; return slave->inactive;
} }
struct bond_net;
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); 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_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(struct net *net, const char *name);
int bond_create_sysfs(void); int bond_create_sysfs(struct bond_net *net);
void bond_destroy_sysfs(void); void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond); void bond_prepare_sysfs_group(struct bonding *bond);
int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave); 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); void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
...@@ -409,6 +411,7 @@ struct bond_net { ...@@ -409,6 +411,7 @@ struct bond_net {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry * proc_dir; struct proc_dir_entry * proc_dir;
#endif #endif
struct class_attribute class_attr_bonding_masters;
}; };
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment