fdtable: Avoid triggering OOMs from alloc_fdmem

Recently due to a spike in connections per second memcached on 3
separate boxes triggered the OOM killer from accept.  At the time the
OOM killer was triggered there was 4GB out of 36GB free in zone 1. The
problem was that alloc_fdtable was allocating an order 3 page (32KiB)
to hold a bitmap, and there was sufficient fragmentation that the
largest page available was 8KiB.

I find the logic that PAGE_ALLOC_COSTLY_ORDER can't fail pretty
dubious but I do agree that order 3 allocations are very likely to
succeed.

There are always pathologies where order > 0 allocations can fail when
there are copious amounts of free memory available.  Using the pigeon
hole principle it is easy to show that it requires 1 page more than
50% of the pages being free to guarantee an order 1 (8KiB) allocation
will succeed, 1 page more than 75% of the pages being free to
guarantee an order 2 (16KiB) allocation will succeed and 1 page more
than 87.5% of the pages being free to guarantee an order 3 allocate
will succeed.

A server churning memory with a lot of small requests and replies like
memcached is a common case that if anything can will skew the odds
against large pages being available.

Therefore let's not give external applications a practical way to kill
linux server applications, and specify __GFP_NORETRY to the kmalloc in
alloc_fdmem.  Unless I am misreading the code and by the time the code
reaches should_alloc_retry in __alloc_pages_slowpath (where
__GFP_NORETRY becomes signification).  We have already tried
everything reasonable to allocate a page and the only thing left to do
is wait.  So not waiting and falling back to vmalloc immediately seems
like the reasonable thing to do even if there wasn't a chance of
triggering the OOM killer.

Cc: stable@vger.kernel.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
1 file changed