diff options
| -rw-r--r-- | net/bridge/br_if.c | 77 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 5 | ||||
| -rw-r--r-- | net/bridge/br_sysfs_if.c | 50 |
3 files changed, 59 insertions, 73 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 | ||
| 109 | static 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 | |||
| 116 | static struct kobj_type brport_ktype = { | ||
| 117 | #ifdef CONFIG_SYSFS | ||
| 118 | .sysfs_ops = &brport_sysfs_ops, | ||
| 119 | #endif | ||
| 120 | .release = release_nbp, | ||
| 121 | }; | ||
| 122 | |||
| 109 | static void destroy_nbp(struct net_bridge_port *p) | 123 | static 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 | ||
| 120 | static void destroy_nbp_rcu(struct rcu_head *head) | 134 | static 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; | ||
| 444 | err2: | ||
| 445 | br_fdb_delete_by_port(br, p); | ||
| 446 | err1: | ||
| 447 | kobject_del(&p->kobj); | ||
| 448 | err0: | ||
| 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); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c5bd631ffcd5..8f10e09f251b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -232,9 +232,8 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); | |||
| 232 | 232 | ||
| 233 | #ifdef CONFIG_SYSFS | 233 | #ifdef CONFIG_SYSFS |
| 234 | /* br_sysfs_if.c */ | 234 | /* br_sysfs_if.c */ |
| 235 | extern struct sysfs_ops brport_sysfs_ops; | ||
| 235 | extern int br_sysfs_addif(struct net_bridge_port *p); | 236 | extern int br_sysfs_addif(struct net_bridge_port *p); |
| 236 | extern void br_sysfs_removeif(struct net_bridge_port *p); | ||
| 237 | extern void br_sysfs_freeif(struct net_bridge_port *p); | ||
| 238 | 237 | ||
| 239 | /* br_sysfs_br.c */ | 238 | /* br_sysfs_br.c */ |
| 240 | extern int br_sysfs_addbr(struct net_device *dev); | 239 | extern int br_sysfs_addbr(struct net_device *dev); |
| @@ -243,8 +242,6 @@ extern void br_sysfs_delbr(struct net_device *dev); | |||
| 243 | #else | 242 | #else |
| 244 | 243 | ||
| 245 | #define br_sysfs_addif(p) (0) | 244 | #define br_sysfs_addif(p) (0) |
| 246 | #define br_sysfs_removeif(p) do { } while(0) | ||
| 247 | #define br_sysfs_freeif(p) kfree(p) | ||
| 248 | #define br_sysfs_addbr(dev) (0) | 245 | #define br_sysfs_addbr(dev) (0) |
| 249 | #define br_sysfs_delbr(dev) do { } while(0) | 246 | #define br_sysfs_delbr(dev) do { } while(0) |
| 250 | #endif /* CONFIG_SYSFS */ | 247 | #endif /* CONFIG_SYSFS */ |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 0ac0355d16dd..c51c9e42aeb3 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
| @@ -195,23 +195,11 @@ static ssize_t brport_store(struct kobject * kobj, | |||
| 195 | return ret; | 195 | return ret; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | /* called from kobject_put when port ref count goes to zero. */ | 198 | struct sysfs_ops brport_sysfs_ops = { |
| 199 | static void brport_release(struct kobject *kobj) | ||
| 200 | { | ||
| 201 | kfree(container_of(kobj, struct net_bridge_port, kobj)); | ||
| 202 | } | ||
| 203 | |||
| 204 | static struct sysfs_ops brport_sysfs_ops = { | ||
| 205 | .show = brport_show, | 199 | .show = brport_show, |
| 206 | .store = brport_store, | 200 | .store = brport_store, |
| 207 | }; | 201 | }; |
| 208 | 202 | ||
| 209 | static struct kobj_type brport_ktype = { | ||
| 210 | .sysfs_ops = &brport_sysfs_ops, | ||
| 211 | .release = brport_release, | ||
| 212 | }; | ||
| 213 | |||
| 214 | |||
| 215 | /* | 203 | /* |
| 216 | * Add sysfs entries to ethernet device added to a bridge. | 204 | * Add sysfs entries to ethernet device added to a bridge. |
| 217 | * Creates a brport subdirectory with bridge attributes. | 205 | * Creates a brport subdirectory with bridge attributes. |
| @@ -223,17 +211,6 @@ int br_sysfs_addif(struct net_bridge_port *p) | |||
| 223 | struct brport_attribute **a; | 211 | struct brport_attribute **a; |
| 224 | int err; | 212 | int err; |
| 225 | 213 | ||
| 226 | ASSERT_RTNL(); | ||
| 227 | |||
| 228 | kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); | ||
| 229 | p->kobj.ktype = &brport_ktype; | ||
| 230 | p->kobj.parent = &(p->dev->class_dev.kobj); | ||
| 231 | p->kobj.kset = NULL; | ||
| 232 | |||
| 233 | err = kobject_add(&p->kobj); | ||
| 234 | if(err) | ||
| 235 | goto out1; | ||
| 236 | |||
| 237 | err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, | 214 | err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, |
| 238 | SYSFS_BRIDGE_PORT_LINK); | 215 | SYSFS_BRIDGE_PORT_LINK); |
| 239 | if (err) | 216 | if (err) |
| @@ -245,28 +222,7 @@ int br_sysfs_addif(struct net_bridge_port *p) | |||
| 245 | goto out2; | 222 | goto out2; |
| 246 | } | 223 | } |
| 247 | 224 | ||
| 248 | err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); | 225 | err= sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); |
| 249 | if (err) | 226 | out2: |
| 250 | goto out2; | ||
| 251 | |||
| 252 | kobject_uevent(&p->kobj, KOBJ_ADD); | ||
| 253 | return 0; | ||
| 254 | out2: | ||
| 255 | kobject_del(&p->kobj); | ||
| 256 | out1: | ||
| 257 | return err; | 227 | return err; |
| 258 | } | 228 | } |
| 259 | |||
| 260 | void br_sysfs_removeif(struct net_bridge_port *p) | ||
| 261 | { | ||
| 262 | pr_debug("br_sysfs_removeif\n"); | ||
| 263 | sysfs_remove_link(&p->br->ifobj, p->dev->name); | ||
| 264 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | ||
| 265 | kobject_del(&p->kobj); | ||
| 266 | } | ||
| 267 | |||
| 268 | void br_sysfs_freeif(struct net_bridge_port *p) | ||
| 269 | { | ||
| 270 | pr_debug("br_sysfs_freeif\n"); | ||
| 271 | kobject_put(&p->kobj); | ||
| 272 | } | ||
