Skip to content

Commit

Permalink
[VLAN]: Move vlan_group allocation to seperate function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 11, 2007
1 parent 2f4284a commit 42429aa
Showing 1 changed file with 41 additions and 37 deletions.
78 changes: 41 additions & 37 deletions net/8021q/vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,34 @@ static void vlan_group_free(struct vlan_group *grp)
kfree(grp);
}

static struct vlan_group *vlan_group_alloc(int ifindex)
{
struct vlan_group *grp;
unsigned int size;
unsigned int i;

grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
if (!grp)
return NULL;

size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;

for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
if (!grp->vlan_devices_arrays[i])
goto err;
}

grp->real_dev_ifindex = ifindex;
hlist_add_head_rcu(&grp->hlist,
&vlan_group_hash[vlan_grp_hashfn(ifindex)]);
return grp;

err:
vlan_group_free(grp);
return NULL;
}

static void vlan_rcu_free(struct rcu_head *rcu)
{
vlan_group_free(container_of(rcu, struct vlan_group, rcu));
Expand Down Expand Up @@ -389,10 +417,9 @@ static void vlan_transfer_operstate(const struct net_device *dev, struct net_dev
static struct net_device *register_vlan_device(struct net_device *real_dev,
unsigned short VLAN_ID)
{
struct vlan_group *grp;
struct vlan_group *grp, *ngrp = NULL;
struct net_device *new_dev;
char name[IFNAMSIZ];
int i;

#ifdef VLAN_DEBUG
printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
Expand Down Expand Up @@ -491,44 +518,24 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
printk(VLAN_DBG "About to go find the group for idx: %i\n",
real_dev->ifindex);
#endif
grp = __vlan_find_group(real_dev->ifindex);
if (!grp) {
ngrp = grp = vlan_group_alloc(real_dev->ifindex);
if (!grp)
goto out_free_newdev;
}

if (register_netdevice(new_dev))
goto out_free_newdev;
goto out_free_group;

vlan_transfer_operstate(real_dev, new_dev);
linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */

/* So, got the sucker initialized, now lets place
* it into our local structure.
*/
grp = __vlan_find_group(real_dev->ifindex);

/* Note, we are running under the RTNL semaphore
* so it cannot "appear" on us.
*/
if (!grp) { /* need to add a new group */
grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
if (!grp)
goto out_free_unregister;

for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
grp->vlan_devices_arrays[i] = kzalloc(
sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
GFP_KERNEL);

if (!grp->vlan_devices_arrays[i])
goto out_free_arrays;
}

/* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
grp->real_dev_ifindex = real_dev->ifindex;

hlist_add_head_rcu(&grp->hlist,
&vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);

if (real_dev->features & NETIF_F_HW_VLAN_RX)
real_dev->vlan_rx_register(real_dev, grp);
}
if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
real_dev->vlan_rx_register(real_dev, ngrp);

vlan_group_set_device(grp, VLAN_ID, new_dev);

Expand All @@ -546,12 +553,9 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
#endif
return new_dev;

out_free_arrays:
vlan_group_free(grp);

out_free_unregister:
unregister_netdev(new_dev);
goto out_ret_null;
out_free_group:
if (ngrp)
vlan_group_free(ngrp);

out_free_newdev:
free_netdev(new_dev);
Expand Down

0 comments on commit 42429aa

Please sign in to comment.