diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 15:05:59 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:14:40 -0400 |
commit | 42429aaee5eb44f4a48fdb056d77d0c06ef5aebc (patch) | |
tree | a23bc4a9464dd3f6323f707246b9738c87ed5482 /net/8021q | |
parent | 2f4284a406cb25d1e41454cbf9ec4545b5ed70a1 (diff) |
[VLAN]: Move vlan_group allocation to seperate function
Move group allocation to a seperate function to clean up the code a bit
and allocate groups before registering the device. Device registration
is globally visible and causes netlink events, so we shouldn't fail
afterwards.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan.c | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index dc95f7cbf291..1b9dc5ecd448 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -197,6 +197,34 @@ static void vlan_group_free(struct vlan_group *grp) | |||
197 | kfree(grp); | 197 | kfree(grp); |
198 | } | 198 | } |
199 | 199 | ||
200 | static struct vlan_group *vlan_group_alloc(int ifindex) | ||
201 | { | ||
202 | struct vlan_group *grp; | ||
203 | unsigned int size; | ||
204 | unsigned int i; | ||
205 | |||
206 | grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); | ||
207 | if (!grp) | ||
208 | return NULL; | ||
209 | |||
210 | size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN; | ||
211 | |||
212 | for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) { | ||
213 | grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL); | ||
214 | if (!grp->vlan_devices_arrays[i]) | ||
215 | goto err; | ||
216 | } | ||
217 | |||
218 | grp->real_dev_ifindex = ifindex; | ||
219 | hlist_add_head_rcu(&grp->hlist, | ||
220 | &vlan_group_hash[vlan_grp_hashfn(ifindex)]); | ||
221 | return grp; | ||
222 | |||
223 | err: | ||
224 | vlan_group_free(grp); | ||
225 | return NULL; | ||
226 | } | ||
227 | |||
200 | static void vlan_rcu_free(struct rcu_head *rcu) | 228 | static void vlan_rcu_free(struct rcu_head *rcu) |
201 | { | 229 | { |
202 | vlan_group_free(container_of(rcu, struct vlan_group, rcu)); | 230 | vlan_group_free(container_of(rcu, struct vlan_group, rcu)); |
@@ -389,10 +417,9 @@ static void vlan_transfer_operstate(const struct net_device *dev, struct net_dev | |||
389 | static struct net_device *register_vlan_device(struct net_device *real_dev, | 417 | static struct net_device *register_vlan_device(struct net_device *real_dev, |
390 | unsigned short VLAN_ID) | 418 | unsigned short VLAN_ID) |
391 | { | 419 | { |
392 | struct vlan_group *grp; | 420 | struct vlan_group *grp, *ngrp = NULL; |
393 | struct net_device *new_dev; | 421 | struct net_device *new_dev; |
394 | char name[IFNAMSIZ]; | 422 | char name[IFNAMSIZ]; |
395 | int i; | ||
396 | 423 | ||
397 | #ifdef VLAN_DEBUG | 424 | #ifdef VLAN_DEBUG |
398 | printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", | 425 | printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", |
@@ -491,9 +518,15 @@ static struct net_device *register_vlan_device(struct net_device *real_dev, | |||
491 | printk(VLAN_DBG "About to go find the group for idx: %i\n", | 518 | printk(VLAN_DBG "About to go find the group for idx: %i\n", |
492 | real_dev->ifindex); | 519 | real_dev->ifindex); |
493 | #endif | 520 | #endif |
521 | grp = __vlan_find_group(real_dev->ifindex); | ||
522 | if (!grp) { | ||
523 | ngrp = grp = vlan_group_alloc(real_dev->ifindex); | ||
524 | if (!grp) | ||
525 | goto out_free_newdev; | ||
526 | } | ||
494 | 527 | ||
495 | if (register_netdevice(new_dev)) | 528 | if (register_netdevice(new_dev)) |
496 | goto out_free_newdev; | 529 | goto out_free_group; |
497 | 530 | ||
498 | vlan_transfer_operstate(real_dev, new_dev); | 531 | vlan_transfer_operstate(real_dev, new_dev); |
499 | linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ | 532 | linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ |
@@ -501,34 +534,8 @@ static struct net_device *register_vlan_device(struct net_device *real_dev, | |||
501 | /* So, got the sucker initialized, now lets place | 534 | /* So, got the sucker initialized, now lets place |
502 | * it into our local structure. | 535 | * it into our local structure. |
503 | */ | 536 | */ |
504 | grp = __vlan_find_group(real_dev->ifindex); | 537 | if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) |
505 | 538 | real_dev->vlan_rx_register(real_dev, ngrp); | |
506 | /* Note, we are running under the RTNL semaphore | ||
507 | * so it cannot "appear" on us. | ||
508 | */ | ||
509 | if (!grp) { /* need to add a new group */ | ||
510 | grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); | ||
511 | if (!grp) | ||
512 | goto out_free_unregister; | ||
513 | |||
514 | for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) { | ||
515 | grp->vlan_devices_arrays[i] = kzalloc( | ||
516 | sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN, | ||
517 | GFP_KERNEL); | ||
518 | |||
519 | if (!grp->vlan_devices_arrays[i]) | ||
520 | goto out_free_arrays; | ||
521 | } | ||
522 | |||
523 | /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */ | ||
524 | grp->real_dev_ifindex = real_dev->ifindex; | ||
525 | |||
526 | hlist_add_head_rcu(&grp->hlist, | ||
527 | &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]); | ||
528 | |||
529 | if (real_dev->features & NETIF_F_HW_VLAN_RX) | ||
530 | real_dev->vlan_rx_register(real_dev, grp); | ||
531 | } | ||
532 | 539 | ||
533 | vlan_group_set_device(grp, VLAN_ID, new_dev); | 540 | vlan_group_set_device(grp, VLAN_ID, new_dev); |
534 | 541 | ||
@@ -546,12 +553,9 @@ static struct net_device *register_vlan_device(struct net_device *real_dev, | |||
546 | #endif | 553 | #endif |
547 | return new_dev; | 554 | return new_dev; |
548 | 555 | ||
549 | out_free_arrays: | 556 | out_free_group: |
550 | vlan_group_free(grp); | 557 | if (ngrp) |
551 | 558 | vlan_group_free(ngrp); | |
552 | out_free_unregister: | ||
553 | unregister_netdev(new_dev); | ||
554 | goto out_ret_null; | ||
555 | 559 | ||
556 | out_free_newdev: | 560 | out_free_newdev: |
557 | free_netdev(new_dev); | 561 | free_netdev(new_dev); |