aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDan Aloni <da-x@monatomic.org>2007-03-02 23:44:51 -0500
committerDavid S. Miller <davem@davemloft.net>2007-03-02 23:44:51 -0500
commit5c15bdec5c38f4ccf73ef2585fc80a6164de9554 (patch)
treec99084e96238eb9ce40e8d9d90e0097c4e92111d /net
parentb5284e5aa94be2f88dc92b29e97aff3da0c45f9f (diff)
[VLAN]: Avoid a 4-order allocation.
This patch splits the vlan_group struct into a multi-allocated struct. On x86_64, the size of the original struct is a little more than 32KB, causing a 4-order allocation, which is prune to problems caused by buddy-system external fragmentation conditions. I couldn't just use vmalloc() because vfree() cannot be called in the softirq context of the RCU callback. Signed-off-by: Dan Aloni <da-x@monatomic.org> Acked-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/8021q/vlan.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index c1c205fad4fb..eb1c71ed7dfe 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -184,14 +184,23 @@ struct net_device *__find_vlan_dev(struct net_device *real_dev,
184 struct vlan_group *grp = __vlan_find_group(real_dev->ifindex); 184 struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
185 185
186 if (grp) 186 if (grp)
187 return grp->vlan_devices[VID]; 187 return vlan_group_get_device(grp, VID);
188 188
189 return NULL; 189 return NULL;
190} 190}
191 191
192static void vlan_group_free(struct vlan_group *grp)
193{
194 int i;
195
196 for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++)
197 kfree(grp->vlan_devices_arrays[i]);
198 kfree(grp);
199}
200
192static void vlan_rcu_free(struct rcu_head *rcu) 201static void vlan_rcu_free(struct rcu_head *rcu)
193{ 202{
194 kfree(container_of(rcu, struct vlan_group, rcu)); 203 vlan_group_free(container_of(rcu, struct vlan_group, rcu));
195} 204}
196 205
197 206
@@ -223,7 +232,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
223 ret = 0; 232 ret = 0;
224 233
225 if (grp) { 234 if (grp) {
226 dev = grp->vlan_devices[vlan_id]; 235 dev = vlan_group_get_device(grp, vlan_id);
227 if (dev) { 236 if (dev) {
228 /* Remove proc entry */ 237 /* Remove proc entry */
229 vlan_proc_rem_dev(dev); 238 vlan_proc_rem_dev(dev);
@@ -237,7 +246,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
237 real_dev->vlan_rx_kill_vid(real_dev, vlan_id); 246 real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
238 } 247 }
239 248
240 grp->vlan_devices[vlan_id] = NULL; 249 vlan_group_set_device(grp, vlan_id, NULL);
241 synchronize_net(); 250 synchronize_net();
242 251
243 252
@@ -251,7 +260,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
251 * group. 260 * group.
252 */ 261 */
253 for (i = 0; i < VLAN_VID_MASK; i++) 262 for (i = 0; i < VLAN_VID_MASK; i++)
254 if (grp->vlan_devices[i]) 263 if (vlan_group_get_device(grp, i))
255 break; 264 break;
256 265
257 if (i == VLAN_VID_MASK) { 266 if (i == VLAN_VID_MASK) {
@@ -379,6 +388,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
379 struct net_device *new_dev; 388 struct net_device *new_dev;
380 struct net_device *real_dev; /* the ethernet device */ 389 struct net_device *real_dev; /* the ethernet device */
381 char name[IFNAMSIZ]; 390 char name[IFNAMSIZ];
391 int i;
382 392
383#ifdef VLAN_DEBUG 393#ifdef VLAN_DEBUG
384 printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", 394 printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
@@ -544,6 +554,15 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
544 if (!grp) 554 if (!grp)
545 goto out_free_unregister; 555 goto out_free_unregister;
546 556
557 for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
558 grp->vlan_devices_arrays[i] = kzalloc(
559 sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
560 GFP_KERNEL);
561
562 if (!grp->vlan_devices_arrays[i])
563 goto out_free_arrays;
564 }
565
547 /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */ 566 /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
548 grp->real_dev_ifindex = real_dev->ifindex; 567 grp->real_dev_ifindex = real_dev->ifindex;
549 568
@@ -554,7 +573,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
554 real_dev->vlan_rx_register(real_dev, grp); 573 real_dev->vlan_rx_register(real_dev, grp);
555 } 574 }
556 575
557 grp->vlan_devices[VLAN_ID] = new_dev; 576 vlan_group_set_device(grp, VLAN_ID, new_dev);
558 577
559 if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */ 578 if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
560 printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n", 579 printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
@@ -571,6 +590,9 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
571#endif 590#endif
572 return new_dev; 591 return new_dev;
573 592
593out_free_arrays:
594 vlan_group_free(grp);
595
574out_free_unregister: 596out_free_unregister:
575 unregister_netdev(new_dev); 597 unregister_netdev(new_dev);
576 goto out_unlock; 598 goto out_unlock;
@@ -606,7 +628,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
606 case NETDEV_CHANGE: 628 case NETDEV_CHANGE:
607 /* Propagate real device state to vlan devices */ 629 /* Propagate real device state to vlan devices */
608 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 630 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
609 vlandev = grp->vlan_devices[i]; 631 vlandev = vlan_group_get_device(grp, i);
610 if (!vlandev) 632 if (!vlandev)
611 continue; 633 continue;
612 634
@@ -617,7 +639,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
617 case NETDEV_DOWN: 639 case NETDEV_DOWN:
618 /* Put all VLANs for this dev in the down state too. */ 640 /* Put all VLANs for this dev in the down state too. */
619 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 641 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
620 vlandev = grp->vlan_devices[i]; 642 vlandev = vlan_group_get_device(grp, i);
621 if (!vlandev) 643 if (!vlandev)
622 continue; 644 continue;
623 645
@@ -632,7 +654,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
632 case NETDEV_UP: 654 case NETDEV_UP:
633 /* Put all VLANs for this dev in the up state too. */ 655 /* Put all VLANs for this dev in the up state too. */
634 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 656 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
635 vlandev = grp->vlan_devices[i]; 657 vlandev = vlan_group_get_device(grp, i);
636 if (!vlandev) 658 if (!vlandev)
637 continue; 659 continue;
638 660
@@ -649,7 +671,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
649 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 671 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
650 int ret; 672 int ret;
651 673
652 vlandev = grp->vlan_devices[i]; 674 vlandev = vlan_group_get_device(grp, i);
653 if (!vlandev) 675 if (!vlandev)
654 continue; 676 continue;
655 677