aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan.c')
-rw-r--r--net/8021q/vlan.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index dbc81b965096..694be86e4490 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -106,29 +106,35 @@ static void vlan_group_free(struct vlan_group *grp)
106static struct vlan_group *vlan_group_alloc(int ifindex) 106static struct vlan_group *vlan_group_alloc(int ifindex)
107{ 107{
108 struct vlan_group *grp; 108 struct vlan_group *grp;
109 unsigned int size;
110 unsigned int i;
111 109
112 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); 110 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
113 if (!grp) 111 if (!grp)
114 return NULL; 112 return NULL;
115 113
116 size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
117
118 for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
119 grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
120 if (!grp->vlan_devices_arrays[i])
121 goto err;
122 }
123
124 grp->real_dev_ifindex = ifindex; 114 grp->real_dev_ifindex = ifindex;
125 hlist_add_head_rcu(&grp->hlist, 115 hlist_add_head_rcu(&grp->hlist,
126 &vlan_group_hash[vlan_grp_hashfn(ifindex)]); 116 &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
127 return grp; 117 return grp;
118}
128 119
129err: 120static int vlan_group_prealloc_vid(struct vlan_group *vg, int vid)
130 vlan_group_free(grp); 121{
131 return NULL; 122 struct net_device **array;
123 unsigned int size;
124
125 ASSERT_RTNL();
126
127 array = vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN];
128 if (array != NULL)
129 return 0;
130
131 size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
132 array = kzalloc(size, GFP_KERNEL);
133 if (array == NULL)
134 return -ENOBUFS;
135
136 vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN] = array;
137 return 0;
132} 138}
133 139
134static void vlan_rcu_free(struct rcu_head *rcu) 140static void vlan_rcu_free(struct rcu_head *rcu)
@@ -247,6 +253,10 @@ int register_vlan_dev(struct net_device *dev)
247 return -ENOBUFS; 253 return -ENOBUFS;
248 } 254 }
249 255
256 err = vlan_group_prealloc_vid(grp, vlan_id);
257 if (err < 0)
258 goto out_free_group;
259
250 err = register_netdevice(dev); 260 err = register_netdevice(dev);
251 if (err < 0) 261 if (err < 0)
252 goto out_free_group; 262 goto out_free_group;
@@ -382,7 +392,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
382 int i, flgs; 392 int i, flgs;
383 struct net_device *vlandev; 393 struct net_device *vlandev;
384 394
385 if (dev->nd_net != &init_net) 395 if (dev_net(dev) != &init_net)
386 return NOTIFY_DONE; 396 return NOTIFY_DONE;
387 397
388 if (!grp) 398 if (!grp)