Commit 7489aec8eed4f2f1eb3b4d35763bd3ea30b32ef5

Authored by Eric Dumazet
Committed by Patrick McHardy
1 parent c936e8bd1d

netfilter: xtables: stackptr should be percpu

commit f3c5c1bfd4 (netfilter: xtables: make ip_tables reentrant)
introduced a performance regression, because stackptr array is shared by
all cpus, adding cache line ping pongs. (16 cpus share a 64 bytes cache
line)

Fix this using alloc_percpu()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-By: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>

Showing 4 changed files with 6 additions and 13 deletions Side-by-side Diff

include/linux/netfilter/x_tables.h
... ... @@ -397,7 +397,7 @@
397 397 * @stacksize jumps (number of user chains) can possibly be made.
398 398 */
399 399 unsigned int stacksize;
400   - unsigned int *stackptr;
  400 + unsigned int __percpu *stackptr;
401 401 void ***jumpstack;
402 402 /* ipt_entry tables: one per CPU */
403 403 /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
net/ipv4/netfilter/ip_tables.c
... ... @@ -336,7 +336,7 @@
336 336 cpu = smp_processor_id();
337 337 table_base = private->entries[cpu];
338 338 jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
339   - stackptr = &private->stackptr[cpu];
  339 + stackptr = per_cpu_ptr(private->stackptr, cpu);
340 340 origptr = *stackptr;
341 341  
342 342 e = get_entry(table_base, private->hook_entry[hook]);
net/ipv6/netfilter/ip6_tables.c
... ... @@ -363,7 +363,7 @@
363 363 cpu = smp_processor_id();
364 364 table_base = private->entries[cpu];
365 365 jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
366   - stackptr = &private->stackptr[cpu];
  366 + stackptr = per_cpu_ptr(private->stackptr, cpu);
367 367 origptr = *stackptr;
368 368  
369 369 e = get_entry(table_base, private->hook_entry[hook]);
net/netfilter/x_tables.c
... ... @@ -699,11 +699,9 @@
699 699 vfree(info->jumpstack);
700 700 else
701 701 kfree(info->jumpstack);
702   - if (sizeof(unsigned int) * nr_cpu_ids > PAGE_SIZE)
703   - vfree(info->stackptr);
704   - else
705   - kfree(info->stackptr);
706 702  
  703 + free_percpu(info->stackptr);
  704 +
707 705 kfree(info);
708 706 }
709 707 EXPORT_SYMBOL(xt_free_table_info);
710 708  
... ... @@ -753,14 +751,9 @@
753 751 unsigned int size;
754 752 int cpu;
755 753  
756   - size = sizeof(unsigned int) * nr_cpu_ids;
757   - if (size > PAGE_SIZE)
758   - i->stackptr = vmalloc(size);
759   - else
760   - i->stackptr = kmalloc(size, GFP_KERNEL);
  754 + i->stackptr = alloc_percpu(unsigned int);
761 755 if (i->stackptr == NULL)
762 756 return -ENOMEM;
763   - memset(i->stackptr, 0, size);
764 757  
765 758 size = sizeof(void **) * nr_cpu_ids;
766 759 if (size > PAGE_SIZE)