Florian Westphal 4cf0b354d9 rhashtable: avoid large lock-array allocations
Sander reports following splat after netfilter nat bysrc table got
converted to rhashtable:

swapper/0: page allocation failure: order:3, mode:0x2084020(GFP_ATOMIC|__GFP_COMP)
 CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.8.0-rc1 [..]
 [<ffffffff811633ed>] warn_alloc_failed+0xdd/0x140
 [<ffffffff811638b1>] __alloc_pages_nodemask+0x3e1/0xcf0
 [<ffffffff811a72ed>] alloc_pages_current+0x8d/0x110
 [<ffffffff8117cb7f>] kmalloc_order+0x1f/0x70
 [<ffffffff811aec19>] __kmalloc+0x129/0x140
 [<ffffffff8146d561>] bucket_table_alloc+0xc1/0x1d0
 [<ffffffff8146da1d>] rhashtable_insert_rehash+0x5d/0xe0
 [<ffffffff819fcfff>] nf_nat_setup_info+0x2ef/0x400

The failure happens when allocating the spinlock array.
Even with GFP_KERNEL its unlikely for such a large allocation
to succeed.

Thomas Graf pointed me at inet_ehash_locks_alloc(), so in addition
to adding NOWARN for atomic allocations this also makes the bucket-array
sizing more conservative.

In commit 095dc8e0c3686 ("tcp: fix/cleanup inet_ehash_locks_alloc()"),
Eric Dumazet says: "Budget 2 cache lines per cpu worth of 'spinlocks'".
IOW, consider size needed by a single spinlock when determining
number of locks per cpu.  So with 64 byte per cacheline and 4 byte per
spinlock this gives 32 locks per cpu.

Resulting size of the lock-array (sizeof(spinlock) == 4):

cpus:    1   2   4   8   16   32   64
old:    1k  1k  4k  8k  16k  16k  16k
new:   128 256 512  1k   2k   4k   8k

8k allocation should have decent chance of success even
with GFP_ATOMIC, and should not fail with GFP_KERNEL.

With 72-byte spinlock (LOCKDEP):
cpus :   1   2
old:    9k 18k
new:   ~2k ~4k

Reported-by: Sander Eikelenboom <linux@eikelenboom.it>
Suggested-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-08-14 21:12:57 -07:00
..
2014-10-09 11:35:48 +03:00
2016-07-29 18:30:16 +08:00
2015-11-23 09:44:58 +01:00
2016-03-17 15:09:34 -07:00
2016-02-29 09:35:20 +01:00
2016-02-07 23:17:59 -08:00
2016-03-02 17:01:55 +02:00
2014-04-30 19:49:37 +01:00
2014-08-06 18:01:25 -07:00
2014-05-05 09:09:14 +02:00
2016-01-19 15:26:55 -05:00
2016-05-23 17:04:14 -07:00
2014-08-08 15:57:25 -07:00
2016-03-09 15:43:42 -08:00
2015-02-12 18:54:15 -08:00
2012-07-30 17:25:16 -07:00
2014-06-25 17:45:43 -07:00
2016-04-23 20:13:24 -04:00
2015-09-08 14:35:59 -07:00
2015-02-12 18:54:16 -08:00
2016-07-06 10:51:14 +01:00
2015-03-23 22:12:08 -04:00
2015-06-25 17:00:40 -07:00
2016-03-17 15:09:34 -07:00
2016-05-30 15:26:57 -07:00
2016-08-02 17:31:41 -04:00