diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2011-10-12 17:56:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-19 19:24:15 -0400 |
commit | 4c22400ab64d434a00ecbe0c655a16956c902aa8 (patch) | |
tree | 7806378cebccfea754fb566b9a707167071ad207 /drivers/net/bonding | |
parent | 672d82c18d222e51b40ff47e660fc54ec3e3e0a9 (diff) |
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>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 7 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 45 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 7 |
3 files changed, 38 insertions, 21 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6191e633728..41430baa132 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -4888,6 +4888,7 @@ static int __net_init bond_net_init(struct net *net) | |||
4888 | INIT_LIST_HEAD(&bn->dev_list); | 4888 | INIT_LIST_HEAD(&bn->dev_list); |
4889 | 4889 | ||
4890 | bond_create_proc_dir(bn); | 4890 | bond_create_proc_dir(bn); |
4891 | bond_create_sysfs(bn); | ||
4891 | 4892 | ||
4892 | return 0; | 4893 | return 0; |
4893 | } | 4894 | } |
@@ -4896,6 +4897,7 @@ static void __net_exit bond_net_exit(struct net *net) | |||
4896 | { | 4897 | { |
4897 | struct bond_net *bn = net_generic(net, bond_net_id); | 4898 | struct bond_net *bn = net_generic(net, bond_net_id); |
4898 | 4899 | ||
4900 | bond_destroy_sysfs(bn); | ||
4899 | bond_destroy_proc_dir(bn); | 4901 | bond_destroy_proc_dir(bn); |
4900 | } | 4902 | } |
4901 | 4903 | ||
@@ -4933,10 +4935,6 @@ static int __init bonding_init(void) | |||
4933 | goto err; | 4935 | goto err; |
4934 | } | 4936 | } |
4935 | 4937 | ||
4936 | res = bond_create_sysfs(); | ||
4937 | if (res) | ||
4938 | goto err; | ||
4939 | |||
4940 | register_netdevice_notifier(&bond_netdev_notifier); | 4938 | register_netdevice_notifier(&bond_netdev_notifier); |
4941 | register_inetaddr_notifier(&bond_inetaddr_notifier); | 4939 | register_inetaddr_notifier(&bond_inetaddr_notifier); |
4942 | out: | 4940 | out: |
@@ -4954,7 +4952,6 @@ static void __exit bonding_exit(void) | |||
4954 | unregister_netdevice_notifier(&bond_netdev_notifier); | 4952 | unregister_netdevice_notifier(&bond_netdev_notifier); |
4955 | unregister_inetaddr_notifier(&bond_inetaddr_notifier); | 4953 | unregister_inetaddr_notifier(&bond_inetaddr_notifier); |
4956 | 4954 | ||
4957 | bond_destroy_sysfs(); | ||
4958 | bond_destroy_debugfs(); | 4955 | bond_destroy_debugfs(); |
4959 | 4956 | ||
4960 | rtnl_link_unregister(&bond_link_ops); | 4957 | rtnl_link_unregister(&bond_link_ops); |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 2dfb4bf9008..6044ff809c2 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -55,8 +55,8 @@ static ssize_t bonding_show_bonds(struct class *cls, | |||
55 | struct class_attribute *attr, | 55 | struct class_attribute *attr, |
56 | char *buf) | 56 | char *buf) |
57 | { | 57 | { |
58 | struct net *net = current->nsproxy->net_ns; | 58 | struct bond_net *bn = |
59 | struct bond_net *bn = net_generic(net, bond_net_id); | 59 | container_of(attr, struct bond_net, class_attr_bonding_masters); |
60 | int res = 0; | 60 | int res = 0; |
61 | struct bonding *bond; | 61 | struct bonding *bond; |
62 | 62 | ||
@@ -79,9 +79,8 @@ static ssize_t bonding_show_bonds(struct class *cls, | |||
79 | return res; | 79 | return res; |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct net_device *bond_get_by_name(struct net *net, const char *ifname) | 82 | static struct net_device *bond_get_by_name(struct bond_net *bn, const char *ifname) |
83 | { | 83 | { |
84 | struct bond_net *bn = net_generic(net, bond_net_id); | ||
85 | struct bonding *bond; | 84 | struct bonding *bond; |
86 | 85 | ||
87 | list_for_each_entry(bond, &bn->dev_list, bond_list) { | 86 | list_for_each_entry(bond, &bn->dev_list, bond_list) { |
@@ -103,7 +102,8 @@ static ssize_t bonding_store_bonds(struct class *cls, | |||
103 | struct class_attribute *attr, | 102 | struct class_attribute *attr, |
104 | const char *buffer, size_t count) | 103 | const char *buffer, size_t count) |
105 | { | 104 | { |
106 | struct net *net = current->nsproxy->net_ns; | 105 | struct bond_net *bn = |
106 | container_of(attr, struct bond_net, class_attr_bonding_masters); | ||
107 | char command[IFNAMSIZ + 1] = {0, }; | 107 | char command[IFNAMSIZ + 1] = {0, }; |
108 | char *ifname; | 108 | char *ifname; |
109 | int rv, res = count; | 109 | int rv, res = count; |
@@ -116,7 +116,7 @@ static ssize_t bonding_store_bonds(struct class *cls, | |||
116 | 116 | ||
117 | if (command[0] == '+') { | 117 | if (command[0] == '+') { |
118 | pr_info("%s is being created...\n", ifname); | 118 | pr_info("%s is being created...\n", ifname); |
119 | rv = bond_create(net, ifname); | 119 | rv = bond_create(bn->net, ifname); |
120 | if (rv) { | 120 | if (rv) { |
121 | if (rv == -EEXIST) | 121 | if (rv == -EEXIST) |
122 | pr_info("%s already exists.\n", ifname); | 122 | pr_info("%s already exists.\n", ifname); |
@@ -128,7 +128,7 @@ static ssize_t bonding_store_bonds(struct class *cls, | |||
128 | struct net_device *bond_dev; | 128 | struct net_device *bond_dev; |
129 | 129 | ||
130 | rtnl_lock(); | 130 | rtnl_lock(); |
131 | bond_dev = bond_get_by_name(net, ifname); | 131 | bond_dev = bond_get_by_name(bn, ifname); |
132 | if (bond_dev) { | 132 | if (bond_dev) { |
133 | pr_info("%s is being deleted...\n", ifname); | 133 | pr_info("%s is being deleted...\n", ifname); |
134 | unregister_netdevice(bond_dev); | 134 | unregister_netdevice(bond_dev); |
@@ -150,9 +150,24 @@ err_no_cmd: | |||
150 | return -EPERM; | 150 | return -EPERM; |
151 | } | 151 | } |
152 | 152 | ||
153 | static const void *bonding_namespace(struct class *cls, | ||
154 | const struct class_attribute *attr) | ||
155 | { | ||
156 | const struct bond_net *bn = | ||
157 | container_of(attr, struct bond_net, class_attr_bonding_masters); | ||
158 | return bn->net; | ||
159 | } | ||
160 | |||
153 | /* class attribute for bond_masters file. This ends up in /sys/class/net */ | 161 | /* class attribute for bond_masters file. This ends up in /sys/class/net */ |
154 | static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, | 162 | static const struct class_attribute class_attr_bonding_masters = { |
155 | bonding_show_bonds, bonding_store_bonds); | 163 | .attr = { |
164 | .name = "bonding_masters", | ||
165 | .mode = S_IWUSR | S_IRUGO, | ||
166 | }, | ||
167 | .show = bonding_show_bonds, | ||
168 | .store = bonding_store_bonds, | ||
169 | .namespace = bonding_namespace, | ||
170 | }; | ||
156 | 171 | ||
157 | int bond_create_slave_symlinks(struct net_device *master, | 172 | int bond_create_slave_symlinks(struct net_device *master, |
158 | struct net_device *slave) | 173 | struct net_device *slave) |
@@ -1655,11 +1670,13 @@ static struct attribute_group bonding_group = { | |||
1655 | * Initialize sysfs. This sets up the bonding_masters file in | 1670 | * Initialize sysfs. This sets up the bonding_masters file in |
1656 | * /sys/class/net. | 1671 | * /sys/class/net. |
1657 | */ | 1672 | */ |
1658 | int bond_create_sysfs(void) | 1673 | int bond_create_sysfs(struct bond_net *bn) |
1659 | { | 1674 | { |
1660 | int ret; | 1675 | int ret; |
1661 | 1676 | ||
1662 | ret = netdev_class_create_file(&class_attr_bonding_masters); | 1677 | bn->class_attr_bonding_masters = class_attr_bonding_masters; |
1678 | |||
1679 | ret = netdev_class_create_file(&bn->class_attr_bonding_masters); | ||
1663 | /* | 1680 | /* |
1664 | * Permit multiple loads of the module by ignoring failures to | 1681 | * Permit multiple loads of the module by ignoring failures to |
1665 | * create the bonding_masters sysfs file. Bonding devices | 1682 | * create the bonding_masters sysfs file. Bonding devices |
@@ -1673,7 +1690,7 @@ int bond_create_sysfs(void) | |||
1673 | */ | 1690 | */ |
1674 | if (ret == -EEXIST) { | 1691 | if (ret == -EEXIST) { |
1675 | /* Is someone being kinky and naming a device bonding_master? */ | 1692 | /* Is someone being kinky and naming a device bonding_master? */ |
1676 | if (__dev_get_by_name(&init_net, | 1693 | if (__dev_get_by_name(bn->net, |
1677 | class_attr_bonding_masters.attr.name)) | 1694 | class_attr_bonding_masters.attr.name)) |
1678 | pr_err("network device named %s already exists in sysfs", | 1695 | pr_err("network device named %s already exists in sysfs", |
1679 | class_attr_bonding_masters.attr.name); | 1696 | class_attr_bonding_masters.attr.name); |
@@ -1687,9 +1704,9 @@ int bond_create_sysfs(void) | |||
1687 | /* | 1704 | /* |
1688 | * Remove /sys/class/net/bonding_masters. | 1705 | * Remove /sys/class/net/bonding_masters. |
1689 | */ | 1706 | */ |
1690 | void bond_destroy_sysfs(void) | 1707 | void bond_destroy_sysfs(struct bond_net *bn) |
1691 | { | 1708 | { |
1692 | netdev_class_remove_file(&class_attr_bonding_masters); | 1709 | netdev_class_remove_file(&bn->class_attr_bonding_masters); |
1693 | } | 1710 | } |
1694 | 1711 | ||
1695 | /* | 1712 | /* |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index e8233661560..82fec5fc75d 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -379,11 +379,13 @@ static inline bool bond_is_slave_inactive(struct slave *slave) | |||
379 | return slave->inactive; | 379 | return slave->inactive; |
380 | } | 380 | } |
381 | 381 | ||
382 | struct bond_net; | ||
383 | |||
382 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); | 384 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); |
383 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); | 385 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); |
384 | int bond_create(struct net *net, const char *name); | 386 | int bond_create(struct net *net, const char *name); |
385 | int bond_create_sysfs(void); | 387 | int bond_create_sysfs(struct bond_net *net); |
386 | void bond_destroy_sysfs(void); | 388 | void bond_destroy_sysfs(struct bond_net *net); |
387 | void bond_prepare_sysfs_group(struct bonding *bond); | 389 | void bond_prepare_sysfs_group(struct bonding *bond); |
388 | int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave); | 390 | int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave); |
389 | void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); | 391 | void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); |
@@ -409,6 +411,7 @@ struct bond_net { | |||
409 | #ifdef CONFIG_PROC_FS | 411 | #ifdef CONFIG_PROC_FS |
410 | struct proc_dir_entry * proc_dir; | 412 | struct proc_dir_entry * proc_dir; |
411 | #endif | 413 | #endif |
414 | struct class_attribute class_attr_bonding_masters; | ||
412 | }; | 415 | }; |
413 | 416 | ||
414 | #ifdef CONFIG_PROC_FS | 417 | #ifdef CONFIG_PROC_FS |