Commit 7489aec8eed4f2f1eb3b4d35763bd3ea30b32ef5
Committed by
Patrick McHardy
1 parent
c936e8bd1d
Exists in
master
and in
39 other branches
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) |