Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -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);
+31 −14
Original line number Diff line number Diff line
@@ -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);
}

/*
+5 −2
Original line number Diff line number Diff line
@@ -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