aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding/bond_sysfs.c')
-rw-r--r--drivers/net/bonding/bond_sysfs.c95
1 files changed, 51 insertions, 44 deletions
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index e3fb7f515150..395f3b160a75 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -68,6 +68,17 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf)
68 return res; 68 return res;
69} 69}
70 70
71static struct net_device *bond_get_by_name(const char *ifname)
72{
73 struct bonding *bond;
74
75 list_for_each_entry(bond, &bond_dev_list, bond_list) {
76 if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
77 return bond->dev;
78 }
79 return NULL;
80}
81
71/* 82/*
72 * "store" function for the bond_masters attribute. This is what 83 * "store" function for the bond_masters attribute. This is what
73 * creates and deletes entire bonds. 84 * creates and deletes entire bonds.
@@ -82,7 +93,6 @@ static ssize_t bonding_store_bonds(struct class *cls,
82 char command[IFNAMSIZ + 1] = {0, }; 93 char command[IFNAMSIZ + 1] = {0, };
83 char *ifname; 94 char *ifname;
84 int rv, res = count; 95 int rv, res = count;
85 struct bonding *bond;
86 96
87 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ 97 sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
88 ifname = command + 1; 98 ifname = command + 1;
@@ -98,41 +108,35 @@ static ssize_t bonding_store_bonds(struct class *cls,
98 pr_info(DRV_NAME ": Bond creation failed.\n"); 108 pr_info(DRV_NAME ": Bond creation failed.\n");
99 res = rv; 109 res = rv;
100 } 110 }
101 goto out; 111 } else if (command[0] == '-') {
102 } 112 struct net_device *bond_dev;
103 113
104 if (command[0] == '-') {
105 rtnl_lock(); 114 rtnl_lock();
115 bond_dev = bond_get_by_name(ifname);
116 if (bond_dev) {
117 pr_info(DRV_NAME ": %s is being deleted...\n",
118 ifname);
119 unregister_netdevice(bond_dev);
120 } else {
121 pr_err(DRV_NAME ": unable to delete non-existent %s\n",
122 ifname);
123 res = -ENODEV;
124 }
125 rtnl_unlock();
126 } else
127 goto err_no_cmd;
106 128
107 list_for_each_entry(bond, &bond_dev_list, bond_list) 129 /* Always return either count or an error. If you return 0, you'll
108 if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { 130 * get called forever, which is bad.
109 pr_info(DRV_NAME 131 */
110 ": %s is being deleted...\n", 132 return res;
111 bond->dev->name);
112 unregister_netdevice(bond->dev);
113 goto out_unlock;
114 }
115
116 pr_err(DRV_NAME
117 ": unable to delete non-existent bond %s\n", ifname);
118 res = -ENODEV;
119 goto out_unlock;
120 }
121 133
122err_no_cmd: 134err_no_cmd:
123 pr_err(DRV_NAME ": no command found in bonding_masters." 135 pr_err(DRV_NAME ": no command found in bonding_masters."
124 " Use +ifname or -ifname.\n"); 136 " Use +ifname or -ifname.\n");
125 return -EPERM; 137 return -EPERM;
126
127out_unlock:
128 rtnl_unlock();
129
130 /* Always return either count or an error. If you return 0, you'll
131 * get called forever, which is bad.
132 */
133out:
134 return res;
135} 138}
139
136/* class attribute for bond_masters file. This ends up in /sys/class/net */ 140/* class attribute for bond_masters file. This ends up in /sys/class/net */
137static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, 141static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
138 bonding_show_bonds, bonding_store_bonds); 142 bonding_show_bonds, bonding_store_bonds);
@@ -233,29 +237,16 @@ static ssize_t bonding_store_slaves(struct device *d,
233 237
234 /* Got a slave name in ifname. Is it already in the list? */ 238 /* Got a slave name in ifname. Is it already in the list? */
235 found = 0; 239 found = 0;
236 read_lock(&bond->lock);
237 bond_for_each_slave(bond, slave, i)
238 if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
239 pr_err(DRV_NAME
240 ": %s: Interface %s is already enslaved!\n",
241 bond->dev->name, ifname);
242 ret = -EPERM;
243 read_unlock(&bond->lock);
244 goto out;
245 }
246 240
247 read_unlock(&bond->lock); 241 /* FIXME: get netns from sysfs object */
248 pr_info(DRV_NAME ": %s: Adding slave %s.\n", 242 dev = __dev_get_by_name(&init_net, ifname);
249 bond->dev->name, ifname);
250 dev = dev_get_by_name(&init_net, ifname);
251 if (!dev) { 243 if (!dev) {
252 pr_info(DRV_NAME 244 pr_info(DRV_NAME
253 ": %s: Interface %s does not exist!\n", 245 ": %s: Interface %s does not exist!\n",
254 bond->dev->name, ifname); 246 bond->dev->name, ifname);
255 ret = -EPERM; 247 ret = -ENODEV;
256 goto out; 248 goto out;
257 } else 249 }
258 dev_put(dev);
259 250
260 if (dev->flags & IFF_UP) { 251 if (dev->flags & IFF_UP) {
261 pr_err(DRV_NAME 252 pr_err(DRV_NAME
@@ -265,6 +256,22 @@ static ssize_t bonding_store_slaves(struct device *d,
265 ret = -EPERM; 256 ret = -EPERM;
266 goto out; 257 goto out;
267 } 258 }
259
260 read_lock(&bond->lock);
261 bond_for_each_slave(bond, slave, i)
262 if (slave->dev == dev) {
263 pr_err(DRV_NAME
264 ": %s: Interface %s is already enslaved!\n",
265 bond->dev->name, ifname);
266 ret = -EPERM;
267 read_unlock(&bond->lock);
268 goto out;
269 }
270 read_unlock(&bond->lock);
271
272 pr_info(DRV_NAME ": %s: Adding slave %s.\n",
273 bond->dev->name, ifname);
274
268 /* If this is the first slave, then we need to set 275 /* If this is the first slave, then we need to set
269 the master's hardware address to be the same as the 276 the master's hardware address to be the same as the
270 slave's. */ 277 slave's. */