Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42429aae authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[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: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2f4284a4
Loading
Loading
Loading
Loading
+41 −37
Original line number Diff line number Diff line
@@ -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));
@@ -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",
@@ -491,9 +518,15 @@ 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() */
@@ -501,34 +534,8 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
	/* 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);

@@ -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);