aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_if.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-02-09 20:10:12 -0500
committerDavid S. Miller <davem@davemloft.net>2006-02-09 20:10:12 -0500
commitbab1deea308afcf9200837d6ac20aefe92972efb (patch)
treebcf3d6ecb431b7b94cdd2a68e12b97abe3c2ebba /net/bridge/br_if.c
parent5dce971acf2ae20c80d5e9d1f6bbf17376870911 (diff)
[BRIDGE]: fix error handling for add interface to bridge
Refactor how the bridge code interacts with kobject system. It should still use kobjects even if not using sysfs. Fix the error unwind handling in br_add_if. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r--net/bridge/br_if.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 70b7ef917234..7fa3a5a9971f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -106,6 +106,20 @@ done:
106 rtnl_unlock(); 106 rtnl_unlock();
107} 107}
108 108
109static void release_nbp(struct kobject *kobj)
110{
111 struct net_bridge_port *p
112 = container_of(kobj, struct net_bridge_port, kobj);
113 kfree(p);
114}
115
116static struct kobj_type brport_ktype = {
117#ifdef CONFIG_SYSFS
118 .sysfs_ops = &brport_sysfs_ops,
119#endif
120 .release = release_nbp,
121};
122
109static void destroy_nbp(struct net_bridge_port *p) 123static void destroy_nbp(struct net_bridge_port *p)
110{ 124{
111 struct net_device *dev = p->dev; 125 struct net_device *dev = p->dev;
@@ -114,7 +128,7 @@ static void destroy_nbp(struct net_bridge_port *p)
114 p->dev = NULL; 128 p->dev = NULL;
115 dev_put(dev); 129 dev_put(dev);
116 130
117 br_sysfs_freeif(p); 131 kobject_put(&p->kobj);
118} 132}
119 133
120static void destroy_nbp_rcu(struct rcu_head *head) 134static void destroy_nbp_rcu(struct rcu_head *head)
@@ -138,6 +152,8 @@ static void del_nbp(struct net_bridge_port *p)
138 struct net_bridge *br = p->br; 152 struct net_bridge *br = p->br;
139 struct net_device *dev = p->dev; 153 struct net_device *dev = p->dev;
140 154
155 sysfs_remove_link(&br->ifobj, dev->name);
156
141 dev_set_promiscuity(dev, -1); 157 dev_set_promiscuity(dev, -1);
142 158
143 cancel_delayed_work(&p->carrier_check); 159 cancel_delayed_work(&p->carrier_check);
@@ -152,6 +168,8 @@ static void del_nbp(struct net_bridge_port *p)
152 168
153 rcu_assign_pointer(dev->br_port, NULL); 169 rcu_assign_pointer(dev->br_port, NULL);
154 170
171 kobject_del(&p->kobj);
172
155 call_rcu(&p->rcu, destroy_nbp_rcu); 173 call_rcu(&p->rcu, destroy_nbp_rcu);
156} 174}
157 175
@@ -161,7 +179,6 @@ static void del_br(struct net_bridge *br)
161 struct net_bridge_port *p, *n; 179 struct net_bridge_port *p, *n;
162 180
163 list_for_each_entry_safe(p, n, &br->port_list, list) { 181 list_for_each_entry_safe(p, n, &br->port_list, list) {
164 br_sysfs_removeif(p);
165 del_nbp(p); 182 del_nbp(p);
166 } 183 }
167 184
@@ -261,6 +278,11 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
261 INIT_WORK(&p->carrier_check, port_carrier_check, dev); 278 INIT_WORK(&p->carrier_check, port_carrier_check, dev);
262 kobject_init(&p->kobj); 279 kobject_init(&p->kobj);
263 280
281 kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
282 p->kobj.ktype = &brport_ktype;
283 p->kobj.parent = &(dev->class_dev.kobj);
284 p->kobj.kset = NULL;
285
264 return p; 286 return p;
265} 287}
266 288
@@ -388,31 +410,43 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
388 if (dev->br_port != NULL) 410 if (dev->br_port != NULL)
389 return -EBUSY; 411 return -EBUSY;
390 412
391 if (IS_ERR(p = new_nbp(br, dev))) 413 p = new_nbp(br, dev);
414 if (IS_ERR(p))
392 return PTR_ERR(p); 415 return PTR_ERR(p);
393 416
394 if ((err = br_fdb_insert(br, p, dev->dev_addr))) 417 err = kobject_add(&p->kobj);
395 destroy_nbp(p); 418 if (err)
396 419 goto err0;
397 else if ((err = br_sysfs_addif(p)))
398 del_nbp(p);
399 else {
400 rcu_assign_pointer(dev->br_port, p);
401 dev_set_promiscuity(dev, 1);
402 420
403 list_add_rcu(&p->list, &br->port_list); 421 err = br_fdb_insert(br, p, dev->dev_addr);
422 if (err)
423 goto err1;
404 424
405 spin_lock_bh(&br->lock); 425 err = br_sysfs_addif(p);
406 br_stp_recalculate_bridge_id(br); 426 if (err)
407 br_features_recompute(br); 427 goto err2;
408 if ((br->dev->flags & IFF_UP)
409 && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
410 br_stp_enable_port(p);
411 spin_unlock_bh(&br->lock);
412 428
413 dev_set_mtu(br->dev, br_min_mtu(br)); 429 rcu_assign_pointer(dev->br_port, p);
414 } 430 dev_set_promiscuity(dev, 1);
431
432 list_add_rcu(&p->list, &br->port_list);
433
434 spin_lock_bh(&br->lock);
435 br_stp_recalculate_bridge_id(br);
436 br_features_recompute(br);
437 schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
438 spin_unlock_bh(&br->lock);
439
440 dev_set_mtu(br->dev, br_min_mtu(br));
441 kobject_uevent(&p->kobj, KOBJ_ADD);
415 442
443 return 0;
444err2:
445 br_fdb_delete_by_port(br, p);
446err1:
447 kobject_del(&p->kobj);
448err0:
449 kobject_put(&p->kobj);
416 return err; 450 return err;
417} 451}
418 452
@@ -424,7 +458,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
424 if (!p || p->br != br) 458 if (!p || p->br != br)
425 return -EINVAL; 459 return -EINVAL;
426 460
427 br_sysfs_removeif(p);
428 del_nbp(p); 461 del_nbp(p);
429 462
430 spin_lock_bh(&br->lock); 463 spin_lock_bh(&br->lock);