2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* linux/mm/slab.c
|
|
|
|
* Written by Mark Hemment, 1996/97.
|
|
|
|
* (markhe@nextd.demon.co.uk)
|
|
|
|
*
|
|
|
|
* kmem_cache_destroy() + some cleanup - 1999 Andrea Arcangeli
|
|
|
|
*
|
|
|
|
* Major cleanup, different bufctl logic, per-cpu arrays
|
|
|
|
* (c) 2000 Manfred Spraul
|
|
|
|
*
|
|
|
|
* Cleanup, make the head arrays unconditional, preparation for NUMA
|
|
|
|
* (c) 2002 Manfred Spraul
|
|
|
|
*
|
|
|
|
* An implementation of the Slab Allocator as described in outline in;
|
|
|
|
* UNIX Internals: The New Frontiers by Uresh Vahalia
|
|
|
|
* Pub: Prentice Hall ISBN 0-13-101908-2
|
|
|
|
* or with a little more detail in;
|
|
|
|
* The Slab Allocator: An Object-Caching Kernel Memory Allocator
|
|
|
|
* Jeff Bonwick (Sun Microsystems).
|
|
|
|
* Presented at: USENIX Summer 1994 Technical Conference
|
|
|
|
*
|
|
|
|
* The memory is organized in caches, one cache for each object type.
|
|
|
|
* (e.g. inode_cache, dentry_cache, buffer_head, vm_area_struct)
|
|
|
|
* Each cache consists out of many slabs (they are small (usually one
|
|
|
|
* page long) and always contiguous), and each slab contains multiple
|
|
|
|
* initialized objects.
|
|
|
|
*
|
|
|
|
* This means, that your constructor is used only for newly allocated
|
2007-10-19 23:27:18 +00:00
|
|
|
* slabs and you must pass objects with the same initializations to
|
2005-04-16 22:20:36 +00:00
|
|
|
* kmem_cache_free.
|
|
|
|
*
|
|
|
|
* Each cache can only support one memory type (GFP_DMA, GFP_HIGHMEM,
|
|
|
|
* normal). If you need a special memory type, then must create a new
|
|
|
|
* cache for that memory type.
|
|
|
|
*
|
|
|
|
* In order to reduce fragmentation, the slabs are sorted in 3 groups:
|
|
|
|
* full slabs with 0 free objects
|
|
|
|
* partial slabs
|
|
|
|
* empty slabs with no allocated objects
|
|
|
|
*
|
|
|
|
* If partial slabs exist, then new allocations come from these slabs,
|
|
|
|
* otherwise from empty slabs or new slabs are allocated.
|
|
|
|
*
|
|
|
|
* kmem_cache_destroy() CAN CRASH if you try to allocate from the cache
|
|
|
|
* during kmem_cache_destroy(). The caller must prevent concurrent allocs.
|
|
|
|
*
|
|
|
|
* Each cache has a short per-cpu head array, most allocs
|
|
|
|
* and frees go into that array, and if that array overflows, then 1/2
|
|
|
|
* of the entries in the array are given back into the global cache.
|
|
|
|
* The head array is strictly LIFO and should improve the cache hit rates.
|
|
|
|
* On SMP, it additionally reduces the spinlock operations.
|
|
|
|
*
|
2006-03-22 08:08:11 +00:00
|
|
|
* The c_cpuarray may not be read with enabled local interrupts -
|
2005-04-16 22:20:36 +00:00
|
|
|
* it's changed with a smp_call_function().
|
|
|
|
*
|
|
|
|
* SMP synchronization:
|
|
|
|
* constructors and destructors are called without any locking.
|
2006-02-01 11:05:50 +00:00
|
|
|
* Several members in struct kmem_cache and struct slab never change, they
|
2005-04-16 22:20:36 +00:00
|
|
|
* are accessed without any locking.
|
|
|
|
* The per-cpu arrays are never accessed from the wrong cpu, no locking,
|
|
|
|
* and local interrupts are disabled so slab code is preempt-safe.
|
|
|
|
* The non-constant members are protected with a per-cache irq spinlock.
|
|
|
|
*
|
|
|
|
* Many thanks to Mark Hemment, who wrote another per-cpu slab patch
|
|
|
|
* in 2000 - many ideas in the current implementation are derived from
|
|
|
|
* his patch.
|
|
|
|
*
|
|
|
|
* Further notes from the original documentation:
|
|
|
|
*
|
|
|
|
* 11 April '97. Started multi-threading - markhe
|
2012-07-06 20:25:12 +00:00
|
|
|
* The global cache-chain is protected by the mutex 'slab_mutex'.
|
2005-04-16 22:20:36 +00:00
|
|
|
* The sem is only needed when accessing/extending the cache-chain, which
|
|
|
|
* can never happen inside an interrupt (kmem_cache_create(),
|
|
|
|
* kmem_cache_shrink() and kmem_cache_reap()).
|
|
|
|
*
|
|
|
|
* At present, each engine can be growing a cache. This should be blocked.
|
|
|
|
*
|
2005-09-09 20:03:32 +00:00
|
|
|
* 15 March 2005. NUMA slab allocator.
|
|
|
|
* Shai Fultheim <shai@scalex86.org>.
|
|
|
|
* Shobhit Dayal <shobhit@calsoftinc.com>
|
|
|
|
* Alok N Kataria <alokk@calsoftinc.com>
|
|
|
|
* Christoph Lameter <christoph@lameter.com>
|
|
|
|
*
|
|
|
|
* Modified the slab allocator to be node aware on NUMA systems.
|
|
|
|
* Each node has its own list of partial, free and full slabs.
|
|
|
|
* All object allocations for a node occur from node specific slab lists.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/mm.h>
|
2006-06-27 09:53:52 +00:00
|
|
|
#include <linux/poison.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/swap.h>
|
|
|
|
#include <linux/cache.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/compiler.h>
|
[PATCH] cpuset memory spread slab cache implementation
Provide the slab cache infrastructure to support cpuset memory spreading.
See the previous patches, cpuset_mem_spread, for an explanation of cpuset
memory spreading.
This patch provides a slab cache SLAB_MEM_SPREAD flag. If set in the
kmem_cache_create() call defining a slab cache, then any task marked with the
process state flag PF_MEMSPREAD will spread memory page allocations for that
cache over all the allowed nodes, instead of preferring the local (faulting)
node.
On systems not configured with CONFIG_NUMA, this results in no change to the
page allocation code path for slab caches.
On systems with cpusets configured in the kernel, but the "memory_spread"
cpuset option not enabled for the current tasks cpuset, this adds a call to a
cpuset routine and failed bit test of the processor state flag PF_SPREAD_SLAB.
For tasks so marked, a second inline test is done for the slab cache flag
SLAB_MEM_SPREAD, and if that is set and if the allocation is not
in_interrupt(), this adds a call to to a cpuset routine that computes which of
the tasks mems_allowed nodes should be preferred for this allocation.
==> This patch adds another hook into the performance critical
code path to allocating objects from the slab cache, in the
____cache_alloc() chunk, below. The next patch optimizes this
hook, reducing the impact of the combined mempolicy plus memory
spreading hooks on this critical code path to a single check
against the tasks task_struct flags word.
This patch provides the generic slab flags and logic needed to apply memory
spreading to a particular slab.
A subsequent patch will mark a few specific slab caches for this placement
policy.
Signed-off-by: Paul Jackson <pj@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-03-24 11:16:07 +00:00
|
|
|
#include <linux/cpuset.h>
|
2008-10-05 20:59:10 +00:00
|
|
|
#include <linux/proc_fs.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/seq_file.h>
|
|
|
|
#include <linux/notifier.h>
|
|
|
|
#include <linux/kallsyms.h>
|
|
|
|
#include <linux/cpu.h>
|
|
|
|
#include <linux/sysctl.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/rcupdate.h>
|
2005-06-23 07:09:02 +00:00
|
|
|
#include <linux/string.h>
|
2006-12-07 04:36:41 +00:00
|
|
|
#include <linux/uaccess.h>
|
2005-09-09 20:03:32 +00:00
|
|
|
#include <linux/nodemask.h>
|
2009-06-11 12:22:40 +00:00
|
|
|
#include <linux/kmemleak.h>
|
2006-01-19 01:42:36 +00:00
|
|
|
#include <linux/mempolicy.h>
|
2006-01-19 01:42:33 +00:00
|
|
|
#include <linux/mutex.h>
|
2006-12-08 10:39:44 +00:00
|
|
|
#include <linux/fault-inject.h>
|
2006-06-27 09:54:55 +00:00
|
|
|
#include <linux/rtmutex.h>
|
2006-12-13 08:34:27 +00:00
|
|
|
#include <linux/reciprocal_div.h>
|
2008-04-30 07:55:01 +00:00
|
|
|
#include <linux/debugobjects.h>
|
2008-05-09 18:35:53 +00:00
|
|
|
#include <linux/kmemcheck.h>
|
2010-03-28 02:40:47 +00:00
|
|
|
#include <linux/memory.h>
|
2011-05-20 19:50:29 +00:00
|
|
|
#include <linux/prefetch.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-31 23:44:30 +00:00
|
|
|
#include <net/sock.h>
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
|
2012-01-09 22:15:42 +00:00
|
|
|
#include <trace/events/kmem.h>
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
#include "internal.h"
|
|
|
|
|
2012-12-18 22:22:46 +00:00
|
|
|
#include "slab.h"
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
2007-05-06 21:50:16 +00:00
|
|
|
* DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
|
2005-04-16 22:20:36 +00:00
|
|
|
* 0 for faster, smaller code (especially in the critical paths).
|
|
|
|
*
|
|
|
|
* STATS - 1 to collect stats for /proc/slabinfo.
|
|
|
|
* 0 for faster, smaller code (especially in the critical paths).
|
|
|
|
*
|
|
|
|
* FORCED_DEBUG - 1 enables SLAB_RED_ZONE and SLAB_POISON (if possible)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_SLAB
|
|
|
|
#define DEBUG 1
|
|
|
|
#define STATS 1
|
|
|
|
#define FORCED_DEBUG 1
|
|
|
|
#else
|
|
|
|
#define DEBUG 0
|
|
|
|
#define STATS 0
|
|
|
|
#define FORCED_DEBUG 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Shouldn't this be in a header file somewhere? */
|
|
|
|
#define BYTES_PER_WORD sizeof(void *)
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
#define REDZONE_ALIGN max(BYTES_PER_WORD, __alignof__(unsigned long long))
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#ifndef ARCH_KMALLOC_FLAGS
|
|
|
|
#define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN
|
|
|
|
#endif
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
/*
|
|
|
|
* true if a page was allocated from pfmemalloc reserves for network-based
|
|
|
|
* swap
|
|
|
|
*/
|
|
|
|
static bool pfmemalloc_active __read_mostly;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* kmem_bufctl_t:
|
|
|
|
*
|
|
|
|
* Bufctl's are used for linking objs within a slab
|
|
|
|
* linked offsets.
|
|
|
|
*
|
|
|
|
* This implementation relies on "struct page" for locating the cache &
|
|
|
|
* slab an object belongs to.
|
|
|
|
* This allows the bufctl structure to be small (one int), but limits
|
|
|
|
* the number of objects a slab (not a cache) can contain when off-slab
|
|
|
|
* bufctls are used. The limit is the size of the largest general cache
|
|
|
|
* that does not use off-slab slabs.
|
|
|
|
* For 32bit archs with 4 kB pages, is this 56.
|
|
|
|
* This is not serious, as it is only for large objects, when it is unwise
|
|
|
|
* to have too many per slab.
|
|
|
|
* Note: This limit can be raised by introducing a general cache whose size
|
|
|
|
* is less than 512 (PAGE_SIZE<<3), but greater than 256.
|
|
|
|
*/
|
|
|
|
|
2005-09-03 22:55:03 +00:00
|
|
|
typedef unsigned int kmem_bufctl_t;
|
2005-04-16 22:20:36 +00:00
|
|
|
#define BUFCTL_END (((kmem_bufctl_t)(~0U))-0)
|
|
|
|
#define BUFCTL_FREE (((kmem_bufctl_t)(~0U))-1)
|
2006-03-25 11:06:39 +00:00
|
|
|
#define BUFCTL_ACTIVE (((kmem_bufctl_t)(~0U))-2)
|
|
|
|
#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-3)
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* struct slab_rcu
|
|
|
|
*
|
|
|
|
* slab_destroy on a SLAB_DESTROY_BY_RCU cache uses this structure to
|
|
|
|
* arrange for kmem_freepages to be called via RCU. This is useful if
|
|
|
|
* we need to approach a kernel structure obliquely, from its address
|
|
|
|
* obtained without the usual locking. We can lock the structure to
|
|
|
|
* stabilize it and check it's still at the given address, only if we
|
|
|
|
* can be sure that the memory has not been meanwhile reused for some
|
|
|
|
* other kind of object (which our subsystem's lock might corrupt).
|
|
|
|
*
|
|
|
|
* rcu_read_lock before reading the address, then rcu_read_unlock after
|
|
|
|
* taking the spinlock within the structure expected at that address.
|
|
|
|
*/
|
|
|
|
struct slab_rcu {
|
2006-01-08 09:00:37 +00:00
|
|
|
struct rcu_head head;
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep;
|
2006-01-08 09:00:37 +00:00
|
|
|
void *addr;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2011-03-10 07:22:24 +00:00
|
|
|
/*
|
|
|
|
* struct slab
|
|
|
|
*
|
|
|
|
* Manages the objs in a slab. Placed either at the beginning of mem allocated
|
|
|
|
* for a slab, or allocated from an general cache.
|
|
|
|
* Slabs are chained into three list: fully used, partial, fully free slabs.
|
|
|
|
*/
|
|
|
|
struct slab {
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
struct list_head list;
|
|
|
|
unsigned long colouroff;
|
|
|
|
void *s_mem; /* including colour offset */
|
|
|
|
unsigned int inuse; /* num of objs active in slab */
|
|
|
|
kmem_bufctl_t free;
|
|
|
|
unsigned short nodeid;
|
|
|
|
};
|
|
|
|
struct slab_rcu __slab_cover_slab_rcu;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* struct array_cache
|
|
|
|
*
|
|
|
|
* Purpose:
|
|
|
|
* - LIFO ordering, to hand out cache-warm objects from _alloc
|
|
|
|
* - reduce the number of linked list operations
|
|
|
|
* - reduce spinlock operations
|
|
|
|
*
|
|
|
|
* The limit is stored in the per-cpu structure to reduce the data cache
|
|
|
|
* footprint.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
struct array_cache {
|
|
|
|
unsigned int avail;
|
|
|
|
unsigned int limit;
|
|
|
|
unsigned int batchcount;
|
|
|
|
unsigned int touched;
|
2005-09-09 20:03:32 +00:00
|
|
|
spinlock_t lock;
|
2007-10-17 06:30:05 +00:00
|
|
|
void *entry[]; /*
|
2006-03-22 08:08:11 +00:00
|
|
|
* Must have this definition in here for the proper
|
|
|
|
* alignment of array_cache. Also simplifies accessing
|
|
|
|
* the entries.
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
*
|
|
|
|
* Entries should not be directly dereferenced as
|
|
|
|
* entries belonging to slabs marked pfmemalloc will
|
|
|
|
* have the lower bits set SLAB_OBJ_PFMEMALLOC
|
2006-03-22 08:08:11 +00:00
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
#define SLAB_OBJ_PFMEMALLOC 1
|
|
|
|
static inline bool is_obj_pfmemalloc(void *objp)
|
|
|
|
{
|
|
|
|
return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void set_obj_pfmemalloc(void **objp)
|
|
|
|
{
|
|
|
|
*objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void clear_obj_pfmemalloc(void **objp)
|
|
|
|
{
|
|
|
|
*objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC);
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* bootstrap: The caches do not work without cpuarrays anymore, but the
|
|
|
|
* cpuarrays are allocated from the generic caches...
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
#define BOOT_CPUCACHE_ENTRIES 1
|
|
|
|
struct arraycache_init {
|
|
|
|
struct array_cache cache;
|
2006-01-08 09:00:37 +00:00
|
|
|
void *entries[BOOT_CPUCACHE_ENTRIES];
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2005-09-09 20:03:32 +00:00
|
|
|
* The slab lists for all objects.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
struct kmem_list3 {
|
2006-01-08 09:00:37 +00:00
|
|
|
struct list_head slabs_partial; /* partial list first, better asm code */
|
|
|
|
struct list_head slabs_full;
|
|
|
|
struct list_head slabs_free;
|
|
|
|
unsigned long free_objects;
|
|
|
|
unsigned int free_limit;
|
2006-02-05 07:27:56 +00:00
|
|
|
unsigned int colour_next; /* Per-node cache coloring */
|
2006-01-08 09:00:37 +00:00
|
|
|
spinlock_t list_lock;
|
|
|
|
struct array_cache *shared; /* shared per node */
|
|
|
|
struct array_cache **alien; /* on other nodes */
|
2006-03-22 08:09:05 +00:00
|
|
|
unsigned long next_reap; /* updated without locking */
|
|
|
|
int free_touched; /* updated without locking */
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
|
|
|
* Need this for bootstrapping a per node allocator.
|
|
|
|
*/
|
2008-01-25 06:20:51 +00:00
|
|
|
#define NUM_INIT_LISTS (3 * MAX_NUMNODES)
|
2011-01-11 23:49:32 +00:00
|
|
|
static struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
|
2005-09-09 20:03:32 +00:00
|
|
|
#define CACHE_CACHE 0
|
2008-01-25 06:20:51 +00:00
|
|
|
#define SIZE_AC MAX_NUMNODES
|
|
|
|
#define SIZE_L3 (2 * MAX_NUMNODES)
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
static int drain_freelist(struct kmem_cache *cache,
|
|
|
|
struct kmem_list3 *l3, int tofree);
|
|
|
|
static void free_block(struct kmem_cache *cachep, void **objpp, int len,
|
|
|
|
int node);
|
2009-06-10 16:40:04 +00:00
|
|
|
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp);
|
2006-11-22 14:55:48 +00:00
|
|
|
static void cache_reap(struct work_struct *unused);
|
2006-06-30 08:55:45 +00:00
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
2006-03-22 08:08:11 +00:00
|
|
|
* This function must be completely optimized away if a constant is passed to
|
|
|
|
* it. Mostly the same as what is in linux/slab.h except it returns an index.
|
2005-09-09 20:03:32 +00:00
|
|
|
*/
|
2005-09-23 04:43:58 +00:00
|
|
|
static __always_inline int index_of(const size_t size)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
2006-02-01 11:05:44 +00:00
|
|
|
extern void __bad_size(void);
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
if (__builtin_constant_p(size)) {
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
#define CACHE(x) \
|
|
|
|
if (size <=x) \
|
|
|
|
return i; \
|
|
|
|
else \
|
|
|
|
i++;
|
2008-03-05 21:58:17 +00:00
|
|
|
#include <linux/kmalloc_sizes.h>
|
2005-09-09 20:03:32 +00:00
|
|
|
#undef CACHE
|
2006-02-01 11:05:44 +00:00
|
|
|
__bad_size();
|
2005-09-23 04:43:58 +00:00
|
|
|
} else
|
2006-02-01 11:05:44 +00:00
|
|
|
__bad_size();
|
2005-09-09 20:03:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-06-23 09:03:46 +00:00
|
|
|
static int slab_early_init = 1;
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
#define INDEX_AC index_of(sizeof(struct arraycache_init))
|
|
|
|
#define INDEX_L3 index_of(sizeof(struct kmem_list3))
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-01 11:05:48 +00:00
|
|
|
static void kmem_list3_init(struct kmem_list3 *parent)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
INIT_LIST_HEAD(&parent->slabs_full);
|
|
|
|
INIT_LIST_HEAD(&parent->slabs_partial);
|
|
|
|
INIT_LIST_HEAD(&parent->slabs_free);
|
|
|
|
parent->shared = NULL;
|
|
|
|
parent->alien = NULL;
|
2006-02-05 07:27:56 +00:00
|
|
|
parent->colour_next = 0;
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_lock_init(&parent->list_lock);
|
|
|
|
parent->free_objects = 0;
|
|
|
|
parent->free_touched = 0;
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
#define MAKE_LIST(cachep, listp, slab, nodeid) \
|
|
|
|
do { \
|
|
|
|
INIT_LIST_HEAD(listp); \
|
|
|
|
list_splice(&(cachep->nodelists[nodeid]->slab), listp); \
|
2005-09-09 20:03:32 +00:00
|
|
|
} while (0)
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
#define MAKE_ALL_LISTS(cachep, ptr, nodeid) \
|
|
|
|
do { \
|
2005-09-09 20:03:32 +00:00
|
|
|
MAKE_LIST((cachep), (&(ptr)->slabs_full), slabs_full, nodeid); \
|
|
|
|
MAKE_LIST((cachep), (&(ptr)->slabs_partial), slabs_partial, nodeid); \
|
|
|
|
MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid); \
|
|
|
|
} while (0)
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#define CFLGS_OFF_SLAB (0x80000000UL)
|
|
|
|
#define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB)
|
|
|
|
|
|
|
|
#define BATCHREFILL_LIMIT 16
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Optimization question: fewer reaps means less probability for unnessary
|
|
|
|
* cpucache drain/refill cycles.
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
2005-11-08 15:44:08 +00:00
|
|
|
* OTOH the cpuarrays can contain lots of objects,
|
2005-04-16 22:20:36 +00:00
|
|
|
* which could lock up otherwise freeable slabs.
|
|
|
|
*/
|
|
|
|
#define REAPTIMEOUT_CPUC (2*HZ)
|
|
|
|
#define REAPTIMEOUT_LIST3 (4*HZ)
|
|
|
|
|
|
|
|
#if STATS
|
|
|
|
#define STATS_INC_ACTIVE(x) ((x)->num_active++)
|
|
|
|
#define STATS_DEC_ACTIVE(x) ((x)->num_active--)
|
|
|
|
#define STATS_INC_ALLOCED(x) ((x)->num_allocations++)
|
|
|
|
#define STATS_INC_GROWN(x) ((x)->grown++)
|
2006-06-30 08:55:45 +00:00
|
|
|
#define STATS_ADD_REAPED(x,y) ((x)->reaped += (y))
|
2006-03-22 08:08:11 +00:00
|
|
|
#define STATS_SET_HIGH(x) \
|
|
|
|
do { \
|
|
|
|
if ((x)->num_active > (x)->high_mark) \
|
|
|
|
(x)->high_mark = (x)->num_active; \
|
|
|
|
} while (0)
|
2005-04-16 22:20:36 +00:00
|
|
|
#define STATS_INC_ERR(x) ((x)->errors++)
|
|
|
|
#define STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
|
2005-09-09 20:03:32 +00:00
|
|
|
#define STATS_INC_NODEFREES(x) ((x)->node_frees++)
|
2006-04-11 05:52:54 +00:00
|
|
|
#define STATS_INC_ACOVERFLOW(x) ((x)->node_overflow++)
|
2006-03-22 08:08:11 +00:00
|
|
|
#define STATS_SET_FREEABLE(x, i) \
|
|
|
|
do { \
|
|
|
|
if ((x)->max_freeable < i) \
|
|
|
|
(x)->max_freeable = i; \
|
|
|
|
} while (0)
|
2005-04-16 22:20:36 +00:00
|
|
|
#define STATS_INC_ALLOCHIT(x) atomic_inc(&(x)->allochit)
|
|
|
|
#define STATS_INC_ALLOCMISS(x) atomic_inc(&(x)->allocmiss)
|
|
|
|
#define STATS_INC_FREEHIT(x) atomic_inc(&(x)->freehit)
|
|
|
|
#define STATS_INC_FREEMISS(x) atomic_inc(&(x)->freemiss)
|
|
|
|
#else
|
|
|
|
#define STATS_INC_ACTIVE(x) do { } while (0)
|
|
|
|
#define STATS_DEC_ACTIVE(x) do { } while (0)
|
|
|
|
#define STATS_INC_ALLOCED(x) do { } while (0)
|
|
|
|
#define STATS_INC_GROWN(x) do { } while (0)
|
2010-08-10 00:19:03 +00:00
|
|
|
#define STATS_ADD_REAPED(x,y) do { (void)(y); } while (0)
|
2005-04-16 22:20:36 +00:00
|
|
|
#define STATS_SET_HIGH(x) do { } while (0)
|
|
|
|
#define STATS_INC_ERR(x) do { } while (0)
|
|
|
|
#define STATS_INC_NODEALLOCS(x) do { } while (0)
|
2005-09-09 20:03:32 +00:00
|
|
|
#define STATS_INC_NODEFREES(x) do { } while (0)
|
2006-04-11 05:52:54 +00:00
|
|
|
#define STATS_INC_ACOVERFLOW(x) do { } while (0)
|
2006-03-22 08:08:11 +00:00
|
|
|
#define STATS_SET_FREEABLE(x, i) do { } while (0)
|
2005-04-16 22:20:36 +00:00
|
|
|
#define STATS_INC_ALLOCHIT(x) do { } while (0)
|
|
|
|
#define STATS_INC_ALLOCMISS(x) do { } while (0)
|
|
|
|
#define STATS_INC_FREEHIT(x) do { } while (0)
|
|
|
|
#define STATS_INC_FREEMISS(x) do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* memory layout of objects:
|
2005-04-16 22:20:36 +00:00
|
|
|
* 0 : objp
|
2006-02-01 11:05:42 +00:00
|
|
|
* 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that
|
2005-04-16 22:20:36 +00:00
|
|
|
* the end of an object is aligned with the end of the real
|
|
|
|
* allocation. Catches writes behind the end of the allocation.
|
2006-02-01 11:05:42 +00:00
|
|
|
* cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1:
|
2005-04-16 22:20:36 +00:00
|
|
|
* redzone word.
|
2006-02-01 11:05:42 +00:00
|
|
|
* cachep->obj_offset: The real object.
|
2012-06-13 15:24:57 +00:00
|
|
|
* cachep->size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
|
|
|
|
* cachep->size - 1* BYTES_PER_WORD: last caller address
|
2006-03-22 08:08:11 +00:00
|
|
|
* [BYTES_PER_WORD long]
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static int obj_offset(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-02-01 11:05:42 +00:00
|
|
|
return cachep->obj_offset;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
return (unsigned long long*) (objp + obj_offset(cachep) -
|
|
|
|
sizeof(unsigned long long));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
2012-06-13 15:24:57 +00:00
|
|
|
return (unsigned long long *)(objp + cachep->size -
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
sizeof(unsigned long long) -
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
REDZONE_ALIGN);
|
2012-06-13 15:24:57 +00:00
|
|
|
return (unsigned long long *) (objp + cachep->size -
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
sizeof(unsigned long long));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void **dbg_userword(struct kmem_cache *cachep, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
BUG_ON(!(cachep->flags & SLAB_STORE_USER));
|
2012-06-13 15:24:57 +00:00
|
|
|
return (void **)(objp + cachep->size - BYTES_PER_WORD);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2006-02-01 11:05:42 +00:00
|
|
|
#define obj_offset(x) 0
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
#define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;})
|
|
|
|
#define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;})
|
2005-04-16 22:20:36 +00:00
|
|
|
#define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;})
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
2011-10-19 05:09:28 +00:00
|
|
|
* Do not go above this order unless 0 objects fit into the slab or
|
|
|
|
* overridden on the command line.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2011-10-19 05:09:24 +00:00
|
|
|
#define SLAB_MAX_ORDER_HI 1
|
|
|
|
#define SLAB_MAX_ORDER_LO 0
|
|
|
|
static int slab_max_order = SLAB_MAX_ORDER_LO;
|
2011-10-19 05:09:28 +00:00
|
|
|
static bool slab_max_order_set __initdata;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-01 11:05:49 +00:00
|
|
|
static inline struct kmem_cache *virt_to_cache(const void *obj)
|
|
|
|
{
|
2007-05-06 21:49:41 +00:00
|
|
|
struct page *page = virt_to_head_page(obj);
|
2012-06-13 15:24:56 +00:00
|
|
|
return page->slab_cache;
|
2006-02-01 11:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct slab *virt_to_slab(const void *obj)
|
|
|
|
{
|
2007-05-06 21:49:41 +00:00
|
|
|
struct page *page = virt_to_head_page(obj);
|
2012-06-13 15:24:56 +00:00
|
|
|
|
|
|
|
VM_BUG_ON(!PageSlab(page));
|
|
|
|
return page->slab_page;
|
2006-02-01 11:05:49 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:10 +00:00
|
|
|
static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab,
|
|
|
|
unsigned int idx)
|
|
|
|
{
|
2012-06-13 15:24:57 +00:00
|
|
|
return slab->s_mem + cache->size * idx;
|
2006-03-22 08:08:10 +00:00
|
|
|
}
|
|
|
|
|
2006-12-13 08:34:27 +00:00
|
|
|
/*
|
2012-06-13 15:24:57 +00:00
|
|
|
* We want to avoid an expensive divide : (offset / cache->size)
|
|
|
|
* Using the fact that size is a constant for a particular cache,
|
|
|
|
* we can replace (offset / cache->size) by
|
2006-12-13 08:34:27 +00:00
|
|
|
* reciprocal_divide(offset, cache->reciprocal_buffer_size)
|
|
|
|
*/
|
|
|
|
static inline unsigned int obj_to_index(const struct kmem_cache *cache,
|
|
|
|
const struct slab *slab, void *obj)
|
2006-03-22 08:08:10 +00:00
|
|
|
{
|
2006-12-13 08:34:27 +00:00
|
|
|
u32 offset = (obj - slab->s_mem);
|
|
|
|
return reciprocal_divide(offset, cache->reciprocal_buffer_size);
|
2006-03-22 08:08:10 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* These are the default caches for kmalloc. Custom caches can have other sizes.
|
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
struct cache_sizes malloc_sizes[] = {
|
|
|
|
#define CACHE(x) { .cs_size = (x) },
|
|
|
|
#include <linux/kmalloc_sizes.h>
|
|
|
|
CACHE(ULONG_MAX)
|
|
|
|
#undef CACHE
|
|
|
|
};
|
|
|
|
EXPORT_SYMBOL(malloc_sizes);
|
|
|
|
|
|
|
|
/* Must match cache_sizes above. Out of line to keep cache footprint low. */
|
|
|
|
struct cache_names {
|
|
|
|
char *name;
|
|
|
|
char *name_dma;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct cache_names __initdata cache_names[] = {
|
|
|
|
#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
|
|
|
|
#include <linux/kmalloc_sizes.h>
|
2006-01-08 09:00:37 +00:00
|
|
|
{NULL,}
|
2005-04-16 22:20:36 +00:00
|
|
|
#undef CACHE
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct arraycache_init initarray_generic =
|
2006-01-08 09:00:37 +00:00
|
|
|
{ {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* internal cache of cache description objs */
|
2012-09-05 00:20:33 +00:00
|
|
|
static struct kmem_cache kmem_cache_boot = {
|
2006-01-08 09:00:37 +00:00
|
|
|
.batchcount = 1,
|
|
|
|
.limit = BOOT_CPUCACHE_ENTRIES,
|
|
|
|
.shared = 1,
|
2012-06-13 15:24:57 +00:00
|
|
|
.size = sizeof(struct kmem_cache),
|
2006-01-08 09:00:37 +00:00
|
|
|
.name = "kmem_cache",
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2006-09-26 06:31:38 +00:00
|
|
|
#define BAD_ALIEN_MAGIC 0x01020304ul
|
|
|
|
|
2006-07-13 12:46:03 +00:00
|
|
|
#ifdef CONFIG_LOCKDEP
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Slab sometimes uses the kmalloc slabs to store the slab headers
|
|
|
|
* for other slabs "off slab".
|
|
|
|
* The locking for this is tricky in that it nests within the locks
|
|
|
|
* of all other slabs in a few places; to deal with this special
|
|
|
|
* locking we put on-slab caches into a separate lock-class.
|
2006-09-26 06:31:38 +00:00
|
|
|
*
|
|
|
|
* We set lock class for alien array caches which are up during init.
|
|
|
|
* The lock annotation will be lost if all cpus of a node goes down and
|
|
|
|
* then comes back up during hotplug
|
2006-07-13 12:46:03 +00:00
|
|
|
*/
|
2006-09-26 06:31:38 +00:00
|
|
|
static struct lock_class_key on_slab_l3_key;
|
|
|
|
static struct lock_class_key on_slab_alc_key;
|
|
|
|
|
2011-07-22 13:26:05 +00:00
|
|
|
static struct lock_class_key debugobj_l3_key;
|
|
|
|
static struct lock_class_key debugobj_alc_key;
|
|
|
|
|
|
|
|
static void slab_set_lock_classes(struct kmem_cache *cachep,
|
|
|
|
struct lock_class_key *l3_key, struct lock_class_key *alc_key,
|
|
|
|
int q)
|
|
|
|
{
|
|
|
|
struct array_cache **alc;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
l3 = cachep->nodelists[q];
|
|
|
|
if (!l3)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lockdep_set_class(&l3->list_lock, l3_key);
|
|
|
|
alc = l3->alien;
|
|
|
|
/*
|
|
|
|
* FIXME: This check for BAD_ALIEN_MAGIC
|
|
|
|
* should go away when common slab code is taught to
|
|
|
|
* work even without alien caches.
|
|
|
|
* Currently, non NUMA code returns BAD_ALIEN_MAGIC
|
|
|
|
* for alloc_alien_cache,
|
|
|
|
*/
|
|
|
|
if (!alc || (unsigned long)alc == BAD_ALIEN_MAGIC)
|
|
|
|
return;
|
|
|
|
for_each_node(r) {
|
|
|
|
if (alc[r])
|
|
|
|
lockdep_set_class(&alc[r]->lock, alc_key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node)
|
|
|
|
{
|
|
|
|
slab_set_lock_classes(cachep, &debugobj_l3_key, &debugobj_alc_key, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
|
|
|
for_each_online_node(node)
|
|
|
|
slab_set_debugobj_lock_classes_node(cachep, node);
|
|
|
|
}
|
|
|
|
|
2009-11-23 20:01:15 +00:00
|
|
|
static void init_node_lock_keys(int q)
|
2006-07-13 12:46:03 +00:00
|
|
|
{
|
2006-09-26 06:31:38 +00:00
|
|
|
struct cache_sizes *s = malloc_sizes;
|
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
if (slab_state < UP)
|
2009-11-23 20:01:15 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) {
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
|
|
|
|
l3 = s->cs_cachep->nodelists[q];
|
|
|
|
if (!l3 || OFF_SLAB(s->cs_cachep))
|
2009-12-27 12:33:14 +00:00
|
|
|
continue;
|
2011-07-22 13:26:05 +00:00
|
|
|
|
|
|
|
slab_set_lock_classes(s->cs_cachep, &on_slab_l3_key,
|
|
|
|
&on_slab_alc_key, q);
|
2006-07-13 12:46:03 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-23 20:01:15 +00:00
|
|
|
|
2012-12-18 22:22:31 +00:00
|
|
|
static void on_slab_lock_classes_node(struct kmem_cache *cachep, int q)
|
|
|
|
{
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
l3 = cachep->nodelists[q];
|
|
|
|
if (!l3)
|
|
|
|
return;
|
|
|
|
|
|
|
|
slab_set_lock_classes(cachep, &on_slab_l3_key,
|
|
|
|
&on_slab_alc_key, q);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void on_slab_lock_classes(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
|
|
|
VM_BUG_ON(OFF_SLAB(cachep));
|
|
|
|
for_each_node(node)
|
|
|
|
on_slab_lock_classes_node(cachep, node);
|
|
|
|
}
|
|
|
|
|
2009-11-23 20:01:15 +00:00
|
|
|
static inline void init_lock_keys(void)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
|
|
|
for_each_node(node)
|
|
|
|
init_node_lock_keys(node);
|
|
|
|
}
|
2006-07-13 12:46:03 +00:00
|
|
|
#else
|
2009-11-23 20:01:15 +00:00
|
|
|
static void init_node_lock_keys(int q)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-09-26 06:31:38 +00:00
|
|
|
static inline void init_lock_keys(void)
|
2006-07-13 12:46:03 +00:00
|
|
|
{
|
|
|
|
}
|
2011-07-22 13:26:05 +00:00
|
|
|
|
2012-12-18 22:22:31 +00:00
|
|
|
static inline void on_slab_lock_classes(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void on_slab_lock_classes_node(struct kmem_cache *cachep, int node)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-07-22 13:26:05 +00:00
|
|
|
static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
}
|
2006-07-13 12:46:03 +00:00
|
|
|
#endif
|
|
|
|
|
2009-10-29 13:34:13 +00:00
|
|
|
static DEFINE_PER_CPU(struct delayed_work, slab_reap_work);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
return cachep->array[smp_processor_id()];
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static inline struct kmem_cache *__find_general_cachep(size_t size,
|
|
|
|
gfp_t gfpflags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct cache_sizes *csizep = malloc_sizes;
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
/* This happens if someone tries to call
|
2006-01-08 09:00:37 +00:00
|
|
|
* kmem_cache_create(), or __kmalloc(), before
|
|
|
|
* the generic caches are initialized.
|
|
|
|
*/
|
[PATCH] Fix slab BUG_ON() triggered by change in array cache size
With the new changes that we made in the initialization of the slab
allocator, we first setup the cache from which array caches are allocated,
and then the cache, from which kmem_list3's are allocated.
Now if the array cache comes from a cache in which objsize > 32, (in this
instance size-64) then, first size-64 cache will be allocated and then the
size-128 (if this is the cache from which kmem_list3's are going to be
allocated).
So with these new changes, we are not guaranteed that we will be
initializing the malloc_sizes array in a serialized order. Thus there is
a bug in __find_general_cachep, as we are checking whether the first
cache_sizes ptr is NULL.
This is replaced by checking whether the array-cache cache is initialized.
Attached is a patch which does that. Boots fine on a x86-64, with
DEBUG_SPIN, DEBUG_SLAB, and preempt.
Attached is a patch which does that. Boots fine on a x86-64, with
DEBUG_SPIN, DEBUG_SLAB, and preempt.Thanks & Regards, Alok
Signed-off-by: Alok N Kataria <alokk@calsoftinc.com>
Signed-off-by: Shobhit Dayal <shobhitdayal.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-14 19:17:53 +00:00
|
|
|
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
2007-07-17 11:03:22 +00:00
|
|
|
if (!size)
|
|
|
|
return ZERO_SIZE_PTR;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
while (size > csizep->cs_size)
|
|
|
|
csizep++;
|
|
|
|
|
|
|
|
/*
|
2005-09-03 22:54:54 +00:00
|
|
|
* Really subtle: The last entry with cs->cs_size==ULONG_MAX
|
2005-04-16 22:20:36 +00:00
|
|
|
* has cs_{dma,}cachep==NULL. Thus no special case
|
|
|
|
* for large kmalloc calls required.
|
|
|
|
*/
|
2007-02-10 09:43:10 +00:00
|
|
|
#ifdef CONFIG_ZONE_DMA
|
2005-04-16 22:20:36 +00:00
|
|
|
if (unlikely(gfpflags & GFP_DMA))
|
|
|
|
return csizep->cs_dmacachep;
|
2007-02-10 09:43:10 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
return csizep->cs_cachep;
|
|
|
|
}
|
|
|
|
|
2006-09-26 06:31:02 +00:00
|
|
|
static struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
|
2005-05-01 15:58:38 +00:00
|
|
|
{
|
|
|
|
return __find_general_cachep(size, gfpflags);
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:45 +00:00
|
|
|
static size_t slab_mgmt_size(size_t nr_objs, size_t align)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-02-01 11:05:45 +00:00
|
|
|
return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Calculate the number of objects and left-over bytes for a given buffer size.
|
|
|
|
*/
|
2006-02-01 11:05:45 +00:00
|
|
|
static void cache_estimate(unsigned long gfporder, size_t buffer_size,
|
|
|
|
size_t align, int flags, size_t *left_over,
|
|
|
|
unsigned int *num)
|
|
|
|
{
|
|
|
|
int nr_objs;
|
|
|
|
size_t mgmt_size;
|
|
|
|
size_t slab_size = PAGE_SIZE << gfporder;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-01 11:05:45 +00:00
|
|
|
/*
|
|
|
|
* The slab management structure can be either off the slab or
|
|
|
|
* on it. For the latter case, the memory allocated for a
|
|
|
|
* slab is used for:
|
|
|
|
*
|
|
|
|
* - The struct slab
|
|
|
|
* - One kmem_bufctl_t for each object
|
|
|
|
* - Padding to respect alignment of @align
|
|
|
|
* - @buffer_size bytes for each object
|
|
|
|
*
|
|
|
|
* If the slab management structure is off the slab, then the
|
|
|
|
* alignment will already be calculated into the size. Because
|
|
|
|
* the slabs are all pages aligned, the objects will be at the
|
|
|
|
* correct alignment when allocated.
|
|
|
|
*/
|
|
|
|
if (flags & CFLGS_OFF_SLAB) {
|
|
|
|
mgmt_size = 0;
|
|
|
|
nr_objs = slab_size / buffer_size;
|
|
|
|
|
|
|
|
if (nr_objs > SLAB_LIMIT)
|
|
|
|
nr_objs = SLAB_LIMIT;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Ignore padding for the initial guess. The padding
|
|
|
|
* is at most @align-1 bytes, and @buffer_size is at
|
|
|
|
* least @align. In the worst case, this result will
|
|
|
|
* be one greater than the number of objects that fit
|
|
|
|
* into the memory allocation when taking the padding
|
|
|
|
* into account.
|
|
|
|
*/
|
|
|
|
nr_objs = (slab_size - sizeof(struct slab)) /
|
|
|
|
(buffer_size + sizeof(kmem_bufctl_t));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This calculated number will be either the right
|
|
|
|
* amount, or one greater than what we want.
|
|
|
|
*/
|
|
|
|
if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
|
|
|
|
> slab_size)
|
|
|
|
nr_objs--;
|
|
|
|
|
|
|
|
if (nr_objs > SLAB_LIMIT)
|
|
|
|
nr_objs = SLAB_LIMIT;
|
|
|
|
|
|
|
|
mgmt_size = slab_mgmt_size(nr_objs, align);
|
|
|
|
}
|
|
|
|
*num = nr_objs;
|
|
|
|
*left_over = slab_size - nr_objs*buffer_size - mgmt_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-09-11 19:49:38 +00:00
|
|
|
#if DEBUG
|
2008-04-30 07:55:07 +00:00
|
|
|
#define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static void __slab_error(const char *function, struct kmem_cache *cachep,
|
|
|
|
char *msg)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
|
2006-01-08 09:00:37 +00:00
|
|
|
function, cachep->name, msg);
|
2005-04-16 22:20:36 +00:00
|
|
|
dump_stack();
|
2013-01-21 06:47:39 +00:00
|
|
|
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2012-09-11 19:49:38 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-12-07 04:32:16 +00:00
|
|
|
/*
|
|
|
|
* By default on NUMA we use alien caches to stage the freeing of
|
|
|
|
* objects allocated from other nodes. This causes massive memory
|
|
|
|
* inefficiencies when using fake NUMA setup to split memory into a
|
|
|
|
* large number of small nodes, so it can be disabled on the command
|
|
|
|
* line
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int use_alien_caches __read_mostly = 1;
|
|
|
|
static int __init noaliencache_setup(char *s)
|
|
|
|
{
|
|
|
|
use_alien_caches = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
__setup("noaliencache", noaliencache_setup);
|
|
|
|
|
2011-10-19 05:09:28 +00:00
|
|
|
static int __init slab_max_order_setup(char *str)
|
|
|
|
{
|
|
|
|
get_option(&str, &slab_max_order);
|
|
|
|
slab_max_order = slab_max_order < 0 ? 0 :
|
|
|
|
min(slab_max_order, MAX_ORDER - 1);
|
|
|
|
slab_max_order_set = true;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
__setup("slab_max_order=", slab_max_order_setup);
|
|
|
|
|
2006-03-10 01:33:54 +00:00
|
|
|
#ifdef CONFIG_NUMA
|
|
|
|
/*
|
|
|
|
* Special reaping functions for NUMA systems called from cache_reap().
|
|
|
|
* These take care of doing round robin flushing of alien caches (containing
|
|
|
|
* objects freed on different nodes from which they were allocated) and the
|
|
|
|
* flushing of remote pcps by calling drain_node_pages.
|
|
|
|
*/
|
2009-10-29 13:34:13 +00:00
|
|
|
static DEFINE_PER_CPU(unsigned long, slab_reap_node);
|
2006-03-10 01:33:54 +00:00
|
|
|
|
|
|
|
static void init_reap_node(int cpu)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
node = next_node(cpu_to_mem(cpu), node_online_map);
|
2006-03-10 01:33:54 +00:00
|
|
|
if (node == MAX_NUMNODES)
|
2006-03-22 08:09:11 +00:00
|
|
|
node = first_node(node_online_map);
|
2006-03-10 01:33:54 +00:00
|
|
|
|
2009-10-29 13:34:13 +00:00
|
|
|
per_cpu(slab_reap_node, cpu) = node;
|
2006-03-10 01:33:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void next_reap_node(void)
|
|
|
|
{
|
2010-12-08 15:22:55 +00:00
|
|
|
int node = __this_cpu_read(slab_reap_node);
|
2006-03-10 01:33:54 +00:00
|
|
|
|
|
|
|
node = next_node(node, node_online_map);
|
|
|
|
if (unlikely(node >= MAX_NUMNODES))
|
|
|
|
node = first_node(node_online_map);
|
2010-12-08 15:22:55 +00:00
|
|
|
__this_cpu_write(slab_reap_node, node);
|
2006-03-10 01:33:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define init_reap_node(cpu) do { } while (0)
|
|
|
|
#define next_reap_node(void) do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Initiate the reap timer running on the target CPU. We run at around 1 to 2Hz
|
|
|
|
* via the workqueue/eventd.
|
|
|
|
* Add the CPU number into the expiration time to minimize the possibility of
|
|
|
|
* the CPUs getting into lockstep and contending for the global cache chain
|
|
|
|
* lock.
|
|
|
|
*/
|
2007-07-16 06:38:20 +00:00
|
|
|
static void __cpuinit start_cpu_timer(int cpu)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-10-29 13:34:13 +00:00
|
|
|
struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When this gets called from do_initcalls via cpucache_init(),
|
|
|
|
* init_workqueues() has already run, so keventd will be setup
|
|
|
|
* at that time.
|
|
|
|
*/
|
2006-11-22 14:54:01 +00:00
|
|
|
if (keventd_up() && reap_work->work.func == NULL) {
|
2006-03-10 01:33:54 +00:00
|
|
|
init_reap_node(cpu);
|
2012-08-21 20:18:23 +00:00
|
|
|
INIT_DEFERRABLE_WORK(reap_work, cache_reap);
|
2006-12-10 10:21:28 +00:00
|
|
|
schedule_delayed_work_on(cpu, reap_work,
|
|
|
|
__round_jiffies_relative(HZ, cpu));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
static struct array_cache *alloc_arraycache(int node, int entries,
|
2009-06-10 16:40:04 +00:00
|
|
|
int batchcount, gfp_t gfp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
int memsize = sizeof(void *) * entries + sizeof(struct array_cache);
|
2005-04-16 22:20:36 +00:00
|
|
|
struct array_cache *nc = NULL;
|
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
nc = kmalloc_node(memsize, gfp, node);
|
2009-06-11 12:22:40 +00:00
|
|
|
/*
|
|
|
|
* The array_cache structures contain pointers to free object.
|
2011-03-31 01:57:33 +00:00
|
|
|
* However, when such objects are allocated or transferred to another
|
2009-06-11 12:22:40 +00:00
|
|
|
* cache the pointers are not cleared and they could be counted as
|
|
|
|
* valid references during a kmemleak scan. Therefore, kmemleak must
|
|
|
|
* not scan such objects.
|
|
|
|
*/
|
|
|
|
kmemleak_no_scan(nc);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (nc) {
|
|
|
|
nc->avail = 0;
|
|
|
|
nc->limit = entries;
|
|
|
|
nc->batchcount = batchcount;
|
|
|
|
nc->touched = 0;
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_lock_init(&nc->lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
return nc;
|
|
|
|
}
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
static inline bool is_slab_pfmemalloc(struct slab *slabp)
|
|
|
|
{
|
|
|
|
struct page *page = virt_to_page(slabp->s_mem);
|
|
|
|
|
|
|
|
return PageSlabPfmemalloc(page);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clears pfmemalloc_active if no slabs have pfmalloc set */
|
|
|
|
static void recheck_pfmemalloc_active(struct kmem_cache *cachep,
|
|
|
|
struct array_cache *ac)
|
|
|
|
{
|
|
|
|
struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()];
|
|
|
|
struct slab *slabp;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
if (!pfmemalloc_active)
|
|
|
|
return;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&l3->list_lock, flags);
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list)
|
|
|
|
if (is_slab_pfmemalloc(slabp))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list)
|
|
|
|
if (is_slab_pfmemalloc(slabp))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_free, list)
|
|
|
|
if (is_slab_pfmemalloc(slabp))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
pfmemalloc_active = false;
|
|
|
|
out:
|
|
|
|
spin_unlock_irqrestore(&l3->list_lock, flags);
|
|
|
|
}
|
|
|
|
|
2012-07-31 23:44:30 +00:00
|
|
|
static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
gfp_t flags, bool force_refill)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
void *objp = ac->entry[--ac->avail];
|
|
|
|
|
|
|
|
/* Ensure the caller is allowed to use objects from PFMEMALLOC slab */
|
|
|
|
if (unlikely(is_obj_pfmemalloc(objp))) {
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
|
|
|
|
if (gfp_pfmemalloc_allowed(flags)) {
|
|
|
|
clear_obj_pfmemalloc(&objp);
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The caller cannot use PFMEMALLOC objects, find another one */
|
2012-09-17 21:09:06 +00:00
|
|
|
for (i = 0; i < ac->avail; i++) {
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
/* If a !PFMEMALLOC object is found, swap them */
|
|
|
|
if (!is_obj_pfmemalloc(ac->entry[i])) {
|
|
|
|
objp = ac->entry[i];
|
|
|
|
ac->entry[i] = ac->entry[ac->avail];
|
|
|
|
ac->entry[ac->avail] = objp;
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are empty slabs on the slabs_free list and we are
|
|
|
|
* being forced to refill the cache, mark this one !pfmemalloc.
|
|
|
|
*/
|
|
|
|
l3 = cachep->nodelists[numa_mem_id()];
|
|
|
|
if (!list_empty(&l3->slabs_free) && force_refill) {
|
|
|
|
struct slab *slabp = virt_to_slab(objp);
|
2012-09-17 21:09:03 +00:00
|
|
|
ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem));
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
clear_obj_pfmemalloc(&objp);
|
|
|
|
recheck_pfmemalloc_active(cachep, ac);
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No !PFMEMALLOC objects available */
|
|
|
|
ac->avail++;
|
|
|
|
objp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2012-07-31 23:44:30 +00:00
|
|
|
static inline void *ac_get_obj(struct kmem_cache *cachep,
|
|
|
|
struct array_cache *ac, gfp_t flags, bool force_refill)
|
|
|
|
{
|
|
|
|
void *objp;
|
|
|
|
|
|
|
|
if (unlikely(sk_memalloc_socks()))
|
|
|
|
objp = __ac_get_obj(cachep, ac, flags, force_refill);
|
|
|
|
else
|
|
|
|
objp = ac->entry[--ac->avail];
|
|
|
|
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
void *objp)
|
|
|
|
{
|
|
|
|
if (unlikely(pfmemalloc_active)) {
|
|
|
|
/* Some pfmemalloc slabs exist, check if this is one */
|
2012-09-17 21:09:03 +00:00
|
|
|
struct page *page = virt_to_head_page(objp);
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
if (PageSlabPfmemalloc(page))
|
|
|
|
set_obj_pfmemalloc(&objp);
|
|
|
|
}
|
|
|
|
|
2012-07-31 23:44:30 +00:00
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
|
|
|
|
void *objp)
|
|
|
|
{
|
|
|
|
if (unlikely(sk_memalloc_socks()))
|
|
|
|
objp = __ac_put_obj(cachep, ac, objp);
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
ac->entry[ac->avail++] = objp;
|
|
|
|
}
|
|
|
|
|
2006-03-25 11:06:44 +00:00
|
|
|
/*
|
|
|
|
* Transfer objects in one arraycache to another.
|
|
|
|
* Locking must be handled by the caller.
|
|
|
|
*
|
|
|
|
* Return the number of entries transferred.
|
|
|
|
*/
|
|
|
|
static int transfer_objects(struct array_cache *to,
|
|
|
|
struct array_cache *from, unsigned int max)
|
|
|
|
{
|
|
|
|
/* Figure out how many entries to transfer */
|
2010-10-26 21:22:23 +00:00
|
|
|
int nr = min3(from->avail, max, to->limit - to->avail);
|
2006-03-25 11:06:44 +00:00
|
|
|
|
|
|
|
if (!nr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
memcpy(to->entry + to->avail, from->entry + from->avail -nr,
|
|
|
|
sizeof(void *) *nr);
|
|
|
|
|
|
|
|
from->avail -= nr;
|
|
|
|
to->avail += nr;
|
|
|
|
return nr;
|
|
|
|
}
|
|
|
|
|
2006-09-27 08:50:08 +00:00
|
|
|
#ifndef CONFIG_NUMA
|
|
|
|
|
|
|
|
#define drain_alien_cache(cachep, alien) do { } while (0)
|
|
|
|
#define reap_alien(cachep, l3) do { } while (0)
|
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
static inline struct array_cache **alloc_alien_cache(int node, int limit, gfp_t gfp)
|
2006-09-27 08:50:08 +00:00
|
|
|
{
|
|
|
|
return (struct array_cache **)BAD_ALIEN_MAGIC;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void free_alien_cache(struct array_cache **ac_ptr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *alternate_node_alloc(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-12-07 04:32:30 +00:00
|
|
|
static inline void *____cache_alloc_node(struct kmem_cache *cachep,
|
2006-09-27 08:50:08 +00:00
|
|
|
gfp_t flags, int nodeid)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* CONFIG_NUMA */
|
|
|
|
|
2006-12-07 04:32:30 +00:00
|
|
|
static void *____cache_alloc_node(struct kmem_cache *, gfp_t, int);
|
2006-03-24 11:16:08 +00:00
|
|
|
static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
|
2006-01-19 01:42:36 +00:00
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
static struct array_cache **alloc_alien_cache(int node, int limit, gfp_t gfp)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
struct array_cache **ac_ptr;
|
2007-02-20 21:57:52 +00:00
|
|
|
int memsize = sizeof(void *) * nr_node_ids;
|
2005-09-09 20:03:32 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (limit > 1)
|
|
|
|
limit = 12;
|
2010-01-06 07:25:23 +00:00
|
|
|
ac_ptr = kzalloc_node(memsize, gfp, node);
|
2005-09-09 20:03:32 +00:00
|
|
|
if (ac_ptr) {
|
|
|
|
for_each_node(i) {
|
2010-01-06 07:25:23 +00:00
|
|
|
if (i == node || !node_online(i))
|
2005-09-09 20:03:32 +00:00
|
|
|
continue;
|
2009-06-10 16:40:04 +00:00
|
|
|
ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d, gfp);
|
2005-09-09 20:03:32 +00:00
|
|
|
if (!ac_ptr[i]) {
|
2007-11-15 00:58:35 +00:00
|
|
|
for (i--; i >= 0; i--)
|
2005-09-09 20:03:32 +00:00
|
|
|
kfree(ac_ptr[i]);
|
|
|
|
kfree(ac_ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ac_ptr;
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:48 +00:00
|
|
|
static void free_alien_cache(struct array_cache **ac_ptr)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!ac_ptr)
|
|
|
|
return;
|
|
|
|
for_each_node(i)
|
2006-01-08 09:00:37 +00:00
|
|
|
kfree(ac_ptr[i]);
|
2005-09-09 20:03:32 +00:00
|
|
|
kfree(ac_ptr);
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void __drain_alien_cache(struct kmem_cache *cachep,
|
2006-02-01 11:05:48 +00:00
|
|
|
struct array_cache *ac, int node)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
struct kmem_list3 *rl3 = cachep->nodelists[node];
|
|
|
|
|
|
|
|
if (ac->avail) {
|
|
|
|
spin_lock(&rl3->list_lock);
|
2006-03-25 11:06:45 +00:00
|
|
|
/*
|
|
|
|
* Stuff objects into the remote nodes shared array first.
|
|
|
|
* That way we could avoid the overhead of putting the objects
|
|
|
|
* into the free lists and getting them back later.
|
|
|
|
*/
|
2006-04-28 15:54:37 +00:00
|
|
|
if (rl3->shared)
|
|
|
|
transfer_objects(rl3->shared, ac, ac->limit);
|
2006-03-25 11:06:45 +00:00
|
|
|
|
2005-09-23 04:44:02 +00:00
|
|
|
free_block(cachep, ac->entry, ac->avail, node);
|
2005-09-09 20:03:32 +00:00
|
|
|
ac->avail = 0;
|
|
|
|
spin_unlock(&rl3->list_lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-10 01:33:54 +00:00
|
|
|
/*
|
|
|
|
* Called from cache_reap() to regularly drain alien caches round robin.
|
|
|
|
*/
|
|
|
|
static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3)
|
|
|
|
{
|
2010-12-08 15:22:55 +00:00
|
|
|
int node = __this_cpu_read(slab_reap_node);
|
2006-03-10 01:33:54 +00:00
|
|
|
|
|
|
|
if (l3->alien) {
|
|
|
|
struct array_cache *ac = l3->alien[node];
|
2006-03-25 11:06:45 +00:00
|
|
|
|
|
|
|
if (ac && ac->avail && spin_trylock_irq(&ac->lock)) {
|
2006-03-10 01:33:54 +00:00
|
|
|
__drain_alien_cache(cachep, ac, node);
|
|
|
|
spin_unlock_irq(&ac->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static void drain_alien_cache(struct kmem_cache *cachep,
|
|
|
|
struct array_cache **alien)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
int i = 0;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct array_cache *ac;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
for_each_online_node(i) {
|
[PATCH] NUMA slab locking fixes: fix cpu down and up locking
This fixes locking and bugs in cpu_down and cpu_up paths of the NUMA slab
allocator. Sonny Rao <sonny@burdell.org> reported problems sometime back on
POWER5 boxes, when the last cpu on the nodes were being offlined. We could
not reproduce the same on x86_64 because the cpumask (node_to_cpumask) was not
being updated on cpu down. Since that issue is now fixed, we can reproduce
Sonny's problems on x86_64 NUMA, and here is the fix.
The problem earlier was on CPU_DOWN, if it was the last cpu on the node to go
down, the array_caches (shared, alien) and the kmem_list3 of the node were
being freed (kfree) with the kmem_list3 lock held. If the l3 or the
array_caches were to come from the same cache being cleared, we hit on
badness.
This patch cleans up the locking in cpu_up and cpu_down path. We cannot
really free l3 on cpu down because, there is no node offlining yet and even
though a cpu is not yet up, node local memory can be allocated for it. So l3s
are usually allocated at keme_cache_create and destroyed at
kmem_cache_destroy. Hence, we don't need cachep->spinlock protection to get
to the cachep->nodelist[nodeid] either.
Patch survived onlining and offlining on a 4 core 2 node Tyan box with a 4
dbench process running all the time.
Signed-off-by: Alok N Kataria <alokk@calsoftinc.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Cc: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-05 07:27:59 +00:00
|
|
|
ac = alien[i];
|
2005-09-09 20:03:32 +00:00
|
|
|
if (ac) {
|
|
|
|
spin_lock_irqsave(&ac->lock, flags);
|
|
|
|
__drain_alien_cache(cachep, ac, i);
|
|
|
|
spin_unlock_irqrestore(&ac->lock, flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-06-23 09:03:05 +00:00
|
|
|
|
2006-07-13 12:44:38 +00:00
|
|
|
static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
|
2006-06-23 09:03:05 +00:00
|
|
|
{
|
|
|
|
struct slab *slabp = virt_to_slab(objp);
|
|
|
|
int nodeid = slabp->nodeid;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
struct array_cache *alien = NULL;
|
2006-10-06 07:43:52 +00:00
|
|
|
int node;
|
|
|
|
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
node = numa_mem_id();
|
2006-06-23 09:03:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure we are not freeing a object from another node to the array
|
|
|
|
* cache on this cpu.
|
|
|
|
*/
|
2007-05-02 17:27:18 +00:00
|
|
|
if (likely(slabp->nodeid == node))
|
2006-06-23 09:03:05 +00:00
|
|
|
return 0;
|
|
|
|
|
2006-10-06 07:43:52 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-06-23 09:03:05 +00:00
|
|
|
STATS_INC_NODEFREES(cachep);
|
|
|
|
if (l3->alien && l3->alien[nodeid]) {
|
|
|
|
alien = l3->alien[nodeid];
|
2006-07-13 12:44:38 +00:00
|
|
|
spin_lock(&alien->lock);
|
2006-06-23 09:03:05 +00:00
|
|
|
if (unlikely(alien->avail == alien->limit)) {
|
|
|
|
STATS_INC_ACOVERFLOW(cachep);
|
|
|
|
__drain_alien_cache(cachep, alien, nodeid);
|
|
|
|
}
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
ac_put_obj(cachep, alien, objp);
|
2006-06-23 09:03:05 +00:00
|
|
|
spin_unlock(&alien->lock);
|
|
|
|
} else {
|
|
|
|
spin_lock(&(cachep->nodelists[nodeid])->list_lock);
|
|
|
|
free_block(cachep, &objp, 1, nodeid);
|
|
|
|
spin_unlock(&(cachep->nodelists[nodeid])->list_lock);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2005-09-09 20:03:32 +00:00
|
|
|
#endif
|
|
|
|
|
2010-03-28 02:40:47 +00:00
|
|
|
/*
|
|
|
|
* Allocates and initializes nodelists for a node on each slab cache, used for
|
|
|
|
* either memory or cpu hotplug. If memory is being hot-added, the kmem_list3
|
|
|
|
* will be allocated off-node since memory is not yet online for the new node.
|
|
|
|
* When hotplugging memory or a cpu, existing nodelists are not replaced if
|
|
|
|
* already in use.
|
|
|
|
*
|
2012-07-06 20:25:12 +00:00
|
|
|
* Must hold slab_mutex.
|
2010-03-28 02:40:47 +00:00
|
|
|
*/
|
|
|
|
static int init_cache_nodelists_node(int node)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
const int memsize = sizeof(struct kmem_list3);
|
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2010-03-28 02:40:47 +00:00
|
|
|
/*
|
|
|
|
* Set up the size64 kmemlist for cpu before we can
|
|
|
|
* begin anything. Make sure some other cpu on this
|
|
|
|
* node has not already allocated this
|
|
|
|
*/
|
|
|
|
if (!cachep->nodelists[node]) {
|
|
|
|
l3 = kmalloc_node(memsize, GFP_KERNEL, node);
|
|
|
|
if (!l3)
|
|
|
|
return -ENOMEM;
|
|
|
|
kmem_list3_init(l3);
|
|
|
|
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
|
|
|
|
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The l3s don't come and go as CPUs come and
|
2012-07-06 20:25:12 +00:00
|
|
|
* go. slab_mutex is sufficient
|
2010-03-28 02:40:47 +00:00
|
|
|
* protection here.
|
|
|
|
*/
|
|
|
|
cachep->nodelists[node] = l3;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irq(&cachep->nodelists[node]->list_lock);
|
|
|
|
cachep->nodelists[node]->free_limit =
|
|
|
|
(1 + nr_cpus_node(node)) *
|
|
|
|
cachep->batchcount + cachep->num;
|
|
|
|
spin_unlock_irq(&cachep->nodelists[node]->list_lock);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-18 10:05:09 +00:00
|
|
|
static void __cpuinit cpuup_canceled(long cpu)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
struct kmem_list3 *l3 = NULL;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int node = cpu_to_mem(cpu);
|
2009-03-13 04:19:46 +00:00
|
|
|
const struct cpumask *mask = cpumask_of_node(node);
|
2007-10-18 10:05:09 +00:00
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2007-10-18 10:05:09 +00:00
|
|
|
struct array_cache *nc;
|
|
|
|
struct array_cache *shared;
|
|
|
|
struct array_cache **alien;
|
|
|
|
|
|
|
|
/* cpu is dead; no one can alloc from it. */
|
|
|
|
nc = cachep->array[cpu];
|
|
|
|
cachep->array[cpu] = NULL;
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
|
|
|
|
if (!l3)
|
|
|
|
goto free_array_cache;
|
|
|
|
|
|
|
|
spin_lock_irq(&l3->list_lock);
|
|
|
|
|
|
|
|
/* Free limit for this kmem_list3 */
|
|
|
|
l3->free_limit -= cachep->batchcount;
|
|
|
|
if (nc)
|
|
|
|
free_block(cachep, nc->entry, nc->avail, node);
|
|
|
|
|
2009-12-17 17:43:12 +00:00
|
|
|
if (!cpumask_empty(mask)) {
|
2007-10-18 10:05:09 +00:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
goto free_array_cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
shared = l3->shared;
|
|
|
|
if (shared) {
|
|
|
|
free_block(cachep, shared->entry,
|
|
|
|
shared->avail, node);
|
|
|
|
l3->shared = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
alien = l3->alien;
|
|
|
|
l3->alien = NULL;
|
|
|
|
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
|
|
|
|
kfree(shared);
|
|
|
|
if (alien) {
|
|
|
|
drain_alien_cache(cachep, alien);
|
|
|
|
free_alien_cache(alien);
|
|
|
|
}
|
|
|
|
free_array_cache:
|
|
|
|
kfree(nc);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* In the previous loop, all the objects were freed to
|
|
|
|
* the respective cache's slabs, now we can go ahead and
|
|
|
|
* shrink each nodelist to its limit.
|
|
|
|
*/
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2007-10-18 10:05:09 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
drain_freelist(cachep, l3, l3->free_objects);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __cpuinit cpuup_prepare(long cpu)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3 = NULL;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int node = cpu_to_mem(cpu);
|
2010-03-28 02:40:47 +00:00
|
|
|
int err;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-10-18 10:05:09 +00:00
|
|
|
/*
|
|
|
|
* We need to do this right in the beginning since
|
|
|
|
* alloc_arraycache's are going to use this list.
|
|
|
|
* kmalloc_node allows us to add the slab to the right
|
|
|
|
* kmem_list3 and not this cpu's kmem_list3
|
|
|
|
*/
|
2010-03-28 02:40:47 +00:00
|
|
|
err = init_cache_nodelists_node(node);
|
|
|
|
if (err < 0)
|
|
|
|
goto bad;
|
2007-10-18 10:05:09 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we can go ahead with allocating the shared arrays and
|
|
|
|
* array caches
|
|
|
|
*/
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2007-10-18 10:05:09 +00:00
|
|
|
struct array_cache *nc;
|
|
|
|
struct array_cache *shared = NULL;
|
|
|
|
struct array_cache **alien = NULL;
|
|
|
|
|
|
|
|
nc = alloc_arraycache(node, cachep->limit,
|
2009-06-10 16:40:04 +00:00
|
|
|
cachep->batchcount, GFP_KERNEL);
|
2007-10-18 10:05:09 +00:00
|
|
|
if (!nc)
|
|
|
|
goto bad;
|
|
|
|
if (cachep->shared) {
|
|
|
|
shared = alloc_arraycache(node,
|
|
|
|
cachep->shared * cachep->batchcount,
|
2009-06-10 16:40:04 +00:00
|
|
|
0xbaadf00d, GFP_KERNEL);
|
2007-10-18 10:05:11 +00:00
|
|
|
if (!shared) {
|
|
|
|
kfree(nc);
|
2005-04-16 22:20:36 +00:00
|
|
|
goto bad;
|
2007-10-18 10:05:11 +00:00
|
|
|
}
|
2007-10-18 10:05:09 +00:00
|
|
|
}
|
|
|
|
if (use_alien_caches) {
|
2009-06-10 16:40:04 +00:00
|
|
|
alien = alloc_alien_cache(node, cachep->limit, GFP_KERNEL);
|
2007-10-18 10:05:11 +00:00
|
|
|
if (!alien) {
|
|
|
|
kfree(shared);
|
|
|
|
kfree(nc);
|
2007-10-18 10:05:09 +00:00
|
|
|
goto bad;
|
2007-10-18 10:05:11 +00:00
|
|
|
}
|
2007-10-18 10:05:09 +00:00
|
|
|
}
|
|
|
|
cachep->array[cpu] = nc;
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
BUG_ON(!l3);
|
|
|
|
|
|
|
|
spin_lock_irq(&l3->list_lock);
|
|
|
|
if (!l3->shared) {
|
|
|
|
/*
|
|
|
|
* We are serialised from CPU_DEAD or
|
|
|
|
* CPU_UP_CANCELLED by the cpucontrol lock
|
|
|
|
*/
|
|
|
|
l3->shared = shared;
|
|
|
|
shared = NULL;
|
|
|
|
}
|
[PATCH] NUMA slab locking fixes: fix cpu down and up locking
This fixes locking and bugs in cpu_down and cpu_up paths of the NUMA slab
allocator. Sonny Rao <sonny@burdell.org> reported problems sometime back on
POWER5 boxes, when the last cpu on the nodes were being offlined. We could
not reproduce the same on x86_64 because the cpumask (node_to_cpumask) was not
being updated on cpu down. Since that issue is now fixed, we can reproduce
Sonny's problems on x86_64 NUMA, and here is the fix.
The problem earlier was on CPU_DOWN, if it was the last cpu on the node to go
down, the array_caches (shared, alien) and the kmem_list3 of the node were
being freed (kfree) with the kmem_list3 lock held. If the l3 or the
array_caches were to come from the same cache being cleared, we hit on
badness.
This patch cleans up the locking in cpu_up and cpu_down path. We cannot
really free l3 on cpu down because, there is no node offlining yet and even
though a cpu is not yet up, node local memory can be allocated for it. So l3s
are usually allocated at keme_cache_create and destroyed at
kmem_cache_destroy. Hence, we don't need cachep->spinlock protection to get
to the cachep->nodelist[nodeid] either.
Patch survived onlining and offlining on a 4 core 2 node Tyan box with a 4
dbench process running all the time.
Signed-off-by: Alok N Kataria <alokk@calsoftinc.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Cc: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-05 07:27:59 +00:00
|
|
|
#ifdef CONFIG_NUMA
|
2007-10-18 10:05:09 +00:00
|
|
|
if (!l3->alien) {
|
|
|
|
l3->alien = alien;
|
|
|
|
alien = NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2007-10-18 10:05:09 +00:00
|
|
|
#endif
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
kfree(shared);
|
|
|
|
free_alien_cache(alien);
|
2011-07-22 13:26:05 +00:00
|
|
|
if (cachep->flags & SLAB_DEBUG_OBJECTS)
|
|
|
|
slab_set_debugobj_lock_classes_node(cachep, node);
|
2012-12-18 22:22:31 +00:00
|
|
|
else if (!OFF_SLAB(cachep) &&
|
|
|
|
!(cachep->flags & SLAB_DESTROY_BY_RCU))
|
|
|
|
on_slab_lock_classes_node(cachep, node);
|
2007-10-18 10:05:09 +00:00
|
|
|
}
|
2009-11-23 20:01:15 +00:00
|
|
|
init_node_lock_keys(node);
|
|
|
|
|
2007-10-18 10:05:09 +00:00
|
|
|
return 0;
|
|
|
|
bad:
|
2007-10-18 10:05:11 +00:00
|
|
|
cpuup_canceled(cpu);
|
2007-10-18 10:05:09 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __cpuinit cpuup_callback(struct notifier_block *nfb,
|
|
|
|
unsigned long action, void *hcpu)
|
|
|
|
{
|
|
|
|
long cpu = (long)hcpu;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case CPU_UP_PREPARE:
|
|
|
|
case CPU_UP_PREPARE_FROZEN:
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2007-10-18 10:05:09 +00:00
|
|
|
err = cpuup_prepare(cpu);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
case CPU_ONLINE:
|
2007-05-09 09:35:10 +00:00
|
|
|
case CPU_ONLINE_FROZEN:
|
2005-04-16 22:20:36 +00:00
|
|
|
start_cpu_timer(cpu);
|
|
|
|
break;
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
2007-05-09 09:34:22 +00:00
|
|
|
case CPU_DOWN_PREPARE:
|
2007-05-09 09:35:10 +00:00
|
|
|
case CPU_DOWN_PREPARE_FROZEN:
|
2007-05-09 09:34:22 +00:00
|
|
|
/*
|
2012-07-06 20:25:12 +00:00
|
|
|
* Shutdown cache reaper. Note that the slab_mutex is
|
2007-05-09 09:34:22 +00:00
|
|
|
* held so that if cache_reap() is invoked it cannot do
|
|
|
|
* anything expensive but will only modify reap_work
|
|
|
|
* and reschedule the timer.
|
|
|
|
*/
|
2010-12-14 15:21:17 +00:00
|
|
|
cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu));
|
2007-05-09 09:34:22 +00:00
|
|
|
/* Now the cache_reaper is guaranteed to be not running. */
|
2009-10-29 13:34:13 +00:00
|
|
|
per_cpu(slab_reap_work, cpu).work.func = NULL;
|
2007-05-09 09:34:22 +00:00
|
|
|
break;
|
|
|
|
case CPU_DOWN_FAILED:
|
2007-05-09 09:35:10 +00:00
|
|
|
case CPU_DOWN_FAILED_FROZEN:
|
2007-05-09 09:34:22 +00:00
|
|
|
start_cpu_timer(cpu);
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
case CPU_DEAD:
|
2007-05-09 09:35:10 +00:00
|
|
|
case CPU_DEAD_FROZEN:
|
[PATCH] NUMA slab locking fixes: fix cpu down and up locking
This fixes locking and bugs in cpu_down and cpu_up paths of the NUMA slab
allocator. Sonny Rao <sonny@burdell.org> reported problems sometime back on
POWER5 boxes, when the last cpu on the nodes were being offlined. We could
not reproduce the same on x86_64 because the cpumask (node_to_cpumask) was not
being updated on cpu down. Since that issue is now fixed, we can reproduce
Sonny's problems on x86_64 NUMA, and here is the fix.
The problem earlier was on CPU_DOWN, if it was the last cpu on the node to go
down, the array_caches (shared, alien) and the kmem_list3 of the node were
being freed (kfree) with the kmem_list3 lock held. If the l3 or the
array_caches were to come from the same cache being cleared, we hit on
badness.
This patch cleans up the locking in cpu_up and cpu_down path. We cannot
really free l3 on cpu down because, there is no node offlining yet and even
though a cpu is not yet up, node local memory can be allocated for it. So l3s
are usually allocated at keme_cache_create and destroyed at
kmem_cache_destroy. Hence, we don't need cachep->spinlock protection to get
to the cachep->nodelist[nodeid] either.
Patch survived onlining and offlining on a 4 core 2 node Tyan box with a 4
dbench process running all the time.
Signed-off-by: Alok N Kataria <alokk@calsoftinc.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Cc: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-05 07:27:59 +00:00
|
|
|
/*
|
|
|
|
* Even if all the cpus of a node are down, we don't free the
|
|
|
|
* kmem_list3 of any cache. This to avoid a race between
|
|
|
|
* cpu_down, and a kmalloc allocation from another cpu for
|
|
|
|
* memory from the node of the cpu going down. The list3
|
|
|
|
* structure is usually allocated from kmem_cache_create() and
|
|
|
|
* gets destroyed at kmem_cache_destroy().
|
|
|
|
*/
|
2007-10-19 23:27:18 +00:00
|
|
|
/* fall through */
|
[PATCH] mm: slab: eliminate lock_cpu_hotplug from slab
Here's an attempt towards doing away with lock_cpu_hotplug in the slab
subsystem. This approach also fixes a bug which shows up when cpus are
being offlined/onlined and slab caches are being tuned simultaneously.
http://marc.theaimsgroup.com/?l=linux-kernel&m=116098888100481&w=2
The patch has been stress tested overnight on a 2 socket 4 core AMD box with
repeated cpu online and offline, while dbench and kernbench process are
running, and slab caches being tuned at the same time.
There were no lockdep warnings either. (This test on 2,6.18 as 2.6.19-rc
crashes at __drain_pages
http://marc.theaimsgroup.com/?l=linux-kernel&m=116172164217678&w=2 )
The approach here is to hold cache_chain_mutex from CPU_UP_PREPARE until
CPU_ONLINE (similar in approach as worqueue_mutex) . Slab code sensitive
to cpu_online_map (kmem_cache_create, kmem_cache_destroy, slabinfo_write,
__cache_shrink) is already serialized with cache_chain_mutex. (This patch
lengthens cache_chain_mutex hold time at kmem_cache_destroy to cover this).
This patch also takes the cache_chain_sem at kmem_cache_shrink to protect
sanity of cpu_online_map at __cache_shrink, as viewed by slab.
(kmem_cache_shrink->__cache_shrink->drain_cpu_caches). But, really,
kmem_cache_shrink is used at just one place in the acpi subsystem! Do we
really need to keep kmem_cache_shrink at all?
Another note. Looks like a cpu hotplug event can send CPU_UP_CANCELED to
a registered subsystem even if the subsystem did not receive CPU_UP_PREPARE.
This could be due to a subsystem registered for notification earlier than
the current subsystem crapping out with NOTIFY_BAD. Badness can occur with
in the CPU_UP_CANCELED code path at slab if this happens (The same would
apply for workqueue.c as well). To overcome this, we might have to use either
a) a per subsystem flag and avoid handling of CPU_UP_CANCELED, or
b) Use a special notifier events like LOCK_ACQUIRE/RELEASE as Gautham was
using in his experiments, or
c) Do not send CPU_UP_CANCELED to a subsystem which did not receive
CPU_UP_PREPARE.
I would prefer c).
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 04:32:14 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
case CPU_UP_CANCELED:
|
2007-05-09 09:35:10 +00:00
|
|
|
case CPU_UP_CANCELED_FROZEN:
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2007-10-18 10:05:09 +00:00
|
|
|
cpuup_canceled(cpu);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-05-26 21:43:32 +00:00
|
|
|
return notifier_from_errno(err);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-27 09:54:09 +00:00
|
|
|
static struct notifier_block __cpuinitdata cpucache_notifier = {
|
|
|
|
&cpuup_callback, NULL, 0
|
|
|
|
};
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-28 02:40:47 +00:00
|
|
|
#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
|
|
|
|
/*
|
|
|
|
* Drains freelist for a node on each slab cache, used for memory hot-remove.
|
|
|
|
* Returns -EBUSY if all objects cannot be drained so that the node is not
|
|
|
|
* removed.
|
|
|
|
*
|
2012-07-06 20:25:12 +00:00
|
|
|
* Must hold slab_mutex.
|
2010-03-28 02:40:47 +00:00
|
|
|
*/
|
|
|
|
static int __meminit drain_cache_nodelists_node(int node)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
int ret = 0;
|
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2010-03-28 02:40:47 +00:00
|
|
|
struct kmem_list3 *l3;
|
|
|
|
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drain_freelist(cachep, l3, l3->free_objects);
|
|
|
|
|
|
|
|
if (!list_empty(&l3->slabs_full) ||
|
|
|
|
!list_empty(&l3->slabs_partial)) {
|
|
|
|
ret = -EBUSY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __meminit slab_memory_callback(struct notifier_block *self,
|
|
|
|
unsigned long action, void *arg)
|
|
|
|
{
|
|
|
|
struct memory_notify *mnb = arg;
|
|
|
|
int ret = 0;
|
|
|
|
int nid;
|
|
|
|
|
|
|
|
nid = mnb->status_change_nid;
|
|
|
|
if (nid < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case MEM_GOING_ONLINE:
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2010-03-28 02:40:47 +00:00
|
|
|
ret = init_cache_nodelists_node(nid);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2010-03-28 02:40:47 +00:00
|
|
|
break;
|
|
|
|
case MEM_GOING_OFFLINE:
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2010-03-28 02:40:47 +00:00
|
|
|
ret = drain_cache_nodelists_node(nid);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2010-03-28 02:40:47 +00:00
|
|
|
break;
|
|
|
|
case MEM_ONLINE:
|
|
|
|
case MEM_OFFLINE:
|
|
|
|
case MEM_CANCEL_ONLINE:
|
|
|
|
case MEM_CANCEL_OFFLINE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
out:
|
2011-03-22 23:30:49 +00:00
|
|
|
return notifier_from_errno(ret);
|
2010-03-28 02:40:47 +00:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_NUMA && CONFIG_MEMORY_HOTPLUG */
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
|
|
|
* swap the static kmem_list3 with kmalloced memory
|
|
|
|
*/
|
2010-03-28 02:40:47 +00:00
|
|
|
static void __init init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
|
|
|
|
int nodeid)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
struct kmem_list3 *ptr;
|
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_NOWAIT, nodeid);
|
2005-09-09 20:03:32 +00:00
|
|
|
BUG_ON(!ptr);
|
|
|
|
|
|
|
|
memcpy(ptr, list, sizeof(struct kmem_list3));
|
2006-07-03 07:25:28 +00:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->list_lock);
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
MAKE_ALL_LISTS(cachep, ptr, nodeid);
|
|
|
|
cachep->nodelists[nodeid] = ptr;
|
|
|
|
}
|
|
|
|
|
2008-01-25 06:20:51 +00:00
|
|
|
/*
|
|
|
|
* For setting up all the kmem_list3s for cache whose buffer_size is same as
|
|
|
|
* size of kmem_list3.
|
|
|
|
*/
|
|
|
|
static void __init set_up_list3s(struct kmem_cache *cachep, int index)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
|
|
|
for_each_online_node(node) {
|
|
|
|
cachep->nodelists[node] = &initkmem_list3[index + node];
|
|
|
|
cachep->nodelists[node]->next_reap = jiffies +
|
|
|
|
REAPTIMEOUT_LIST3 +
|
|
|
|
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-28 16:23:01 +00:00
|
|
|
/*
|
|
|
|
* The memory after the last cpu cache pointer is used for the
|
|
|
|
* the nodelists pointer.
|
|
|
|
*/
|
|
|
|
static void setup_nodelists_pointer(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Initialisation. Called after the page allocator have been initialised and
|
|
|
|
* before smp_init().
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
void __init kmem_cache_init(void)
|
|
|
|
{
|
|
|
|
struct cache_sizes *sizes;
|
|
|
|
struct cache_names *names;
|
2005-09-09 20:03:32 +00:00
|
|
|
int i;
|
|
|
|
|
2012-09-05 00:20:33 +00:00
|
|
|
kmem_cache = &kmem_cache_boot;
|
2012-11-28 16:23:01 +00:00
|
|
|
setup_nodelists_pointer(kmem_cache);
|
2012-09-05 00:20:33 +00:00
|
|
|
|
2009-06-16 22:32:16 +00:00
|
|
|
if (num_possible_nodes() == 1)
|
2007-05-02 17:27:18 +00:00
|
|
|
use_alien_caches = 0;
|
|
|
|
|
2012-11-28 16:23:01 +00:00
|
|
|
for (i = 0; i < NUM_INIT_LISTS; i++)
|
2005-09-09 20:03:32 +00:00
|
|
|
kmem_list3_init(&initkmem_list3[i]);
|
2012-11-28 16:23:01 +00:00
|
|
|
|
2012-09-05 00:20:33 +00:00
|
|
|
set_up_list3s(kmem_cache, CACHE_CACHE);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Fragmentation resistance on low memory - only use bigger
|
2011-10-19 05:09:28 +00:00
|
|
|
* page orders on machines with more than 32MB of memory if
|
|
|
|
* not overridden on the command line.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2011-10-19 05:09:28 +00:00
|
|
|
if (!slab_max_order_set && totalram_pages > (32 << 20) >> PAGE_SHIFT)
|
2011-10-19 05:09:24 +00:00
|
|
|
slab_max_order = SLAB_MAX_ORDER_HI;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Bootstrap is tricky, because several objects are allocated
|
|
|
|
* from caches that do not exist yet:
|
2012-09-05 00:20:33 +00:00
|
|
|
* 1) initialize the kmem_cache cache: it contains the struct
|
|
|
|
* kmem_cache structures of all caches, except kmem_cache itself:
|
|
|
|
* kmem_cache is statically allocated.
|
2005-09-09 20:03:32 +00:00
|
|
|
* Initially an __init data area is used for the head array and the
|
|
|
|
* kmem_list3 structures, it's replaced with a kmalloc allocated
|
|
|
|
* array at the end of the bootstrap.
|
2005-04-16 22:20:36 +00:00
|
|
|
* 2) Create the first kmalloc cache.
|
2006-02-01 11:05:50 +00:00
|
|
|
* The struct kmem_cache for the new cache is allocated normally.
|
2005-09-09 20:03:32 +00:00
|
|
|
* An __init data area is used for the head array.
|
|
|
|
* 3) Create the remaining kmalloc caches, with minimally sized
|
|
|
|
* head arrays.
|
2012-09-05 00:20:33 +00:00
|
|
|
* 4) Replace the __init data head arrays for kmem_cache and the first
|
2005-04-16 22:20:36 +00:00
|
|
|
* kmalloc cache with kmalloc allocated arrays.
|
2012-09-05 00:20:33 +00:00
|
|
|
* 5) Replace the __init data for kmem_list3 for kmem_cache and
|
2005-09-09 20:03:32 +00:00
|
|
|
* the other cache's with kmalloc allocated memory.
|
|
|
|
* 6) Resize the head arrays of the kmalloc caches to their final sizes.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-05 00:20:33 +00:00
|
|
|
/* 1) create the kmem_cache */
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-05-06 21:49:29 +00:00
|
|
|
/*
|
2011-07-20 17:04:23 +00:00
|
|
|
* struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
|
2007-05-06 21:49:29 +00:00
|
|
|
*/
|
2012-11-28 16:23:09 +00:00
|
|
|
create_boot_cache(kmem_cache, "kmem_cache",
|
|
|
|
offsetof(struct kmem_cache, array[nr_cpu_ids]) +
|
|
|
|
nr_node_ids * sizeof(struct kmem_list3 *),
|
|
|
|
SLAB_HWCACHE_ALIGN);
|
|
|
|
list_add(&kmem_cache->list, &slab_caches);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* 2+3) create the kmalloc caches */
|
|
|
|
sizes = malloc_sizes;
|
|
|
|
names = cache_names;
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Initialize the caches that provide memory for the array cache and the
|
|
|
|
* kmem_list3 structures first. Without this, further allocations will
|
|
|
|
* bug.
|
2005-09-09 20:03:32 +00:00
|
|
|
*/
|
|
|
|
|
2012-11-28 16:23:07 +00:00
|
|
|
sizes[INDEX_AC].cs_cachep = create_kmalloc_cache(names[INDEX_AC].name,
|
|
|
|
sizes[INDEX_AC].cs_size, ARCH_KMALLOC_FLAGS);
|
|
|
|
|
|
|
|
if (INDEX_AC != INDEX_L3)
|
|
|
|
sizes[INDEX_L3].cs_cachep =
|
|
|
|
create_kmalloc_cache(names[INDEX_L3].name,
|
|
|
|
sizes[INDEX_L3].cs_size, ARCH_KMALLOC_FLAGS);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-06-23 09:03:46 +00:00
|
|
|
slab_early_init = 0;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
while (sizes->cs_size != ULONG_MAX) {
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
|
|
|
* For performance, all the general caches are L1 aligned.
|
2005-04-16 22:20:36 +00:00
|
|
|
* This should be particularly beneficial on SMP boxes, as it
|
|
|
|
* eliminates "false sharing".
|
|
|
|
* Note for systems short on memory removing the alignment will
|
2005-09-09 20:03:32 +00:00
|
|
|
* allow tighter packing of the smaller caches.
|
|
|
|
*/
|
2012-11-28 16:23:07 +00:00
|
|
|
if (!sizes->cs_cachep)
|
|
|
|
sizes->cs_cachep = create_kmalloc_cache(names->name,
|
|
|
|
sizes->cs_size, ARCH_KMALLOC_FLAGS);
|
|
|
|
|
2007-02-10 09:43:10 +00:00
|
|
|
#ifdef CONFIG_ZONE_DMA
|
2012-11-28 16:23:07 +00:00
|
|
|
sizes->cs_dmacachep = create_kmalloc_cache(
|
|
|
|
names->name_dma, sizes->cs_size,
|
|
|
|
SLAB_CACHE_DMA|ARCH_KMALLOC_FLAGS);
|
2007-02-10 09:43:10 +00:00
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
sizes++;
|
|
|
|
names++;
|
|
|
|
}
|
|
|
|
/* 4) Replace the bootstrap head arrays */
|
|
|
|
{
|
2006-07-03 07:25:28 +00:00
|
|
|
struct array_cache *ptr;
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2012-09-05 00:20:33 +00:00
|
|
|
memcpy(ptr, cpu_cache_get(kmem_cache),
|
2006-01-08 09:00:37 +00:00
|
|
|
sizeof(struct arraycache_init));
|
2006-07-03 07:25:28 +00:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->lock);
|
|
|
|
|
2012-09-05 00:20:33 +00:00
|
|
|
kmem_cache->array[smp_processor_id()] = ptr;
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-02-01 11:05:49 +00:00
|
|
|
BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
|
2006-01-08 09:00:37 +00:00
|
|
|
!= &initarray_generic.cache);
|
2006-02-01 11:05:49 +00:00
|
|
|
memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
|
2006-01-08 09:00:37 +00:00
|
|
|
sizeof(struct arraycache_init));
|
2006-07-03 07:25:28 +00:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->lock);
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
|
2006-01-08 09:00:37 +00:00
|
|
|
ptr;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2005-09-09 20:03:32 +00:00
|
|
|
/* 5) Replace the bootstrap kmem_list3's */
|
|
|
|
{
|
2006-10-06 07:43:52 +00:00
|
|
|
int nid;
|
|
|
|
|
2008-01-24 13:49:54 +00:00
|
|
|
for_each_online_node(nid) {
|
2012-09-05 00:20:33 +00:00
|
|
|
init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
|
2008-01-25 06:20:51 +00:00
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
init_list(malloc_sizes[INDEX_AC].cs_cachep,
|
2006-10-06 07:43:52 +00:00
|
|
|
&initkmem_list3[SIZE_AC + nid], nid);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
|
|
|
if (INDEX_AC != INDEX_L3) {
|
|
|
|
init_list(malloc_sizes[INDEX_L3].cs_cachep,
|
2006-10-06 07:43:52 +00:00
|
|
|
&initkmem_list3[SIZE_L3 + nid], nid);
|
2005-09-09 20:03:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = UP;
|
2009-06-12 12:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void __init kmem_cache_init_late(void)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = UP;
|
2011-11-28 20:12:40 +00:00
|
|
|
|
2009-06-12 12:58:59 +00:00
|
|
|
/* 6) resize the head arrays to their final sizes */
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
|
|
|
list_for_each_entry(cachep, &slab_caches, list)
|
2009-06-12 12:58:59 +00:00
|
|
|
if (enable_cpucache(cachep, GFP_NOWAIT))
|
|
|
|
BUG();
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2006-09-26 06:31:38 +00:00
|
|
|
|
2012-09-05 02:33:18 +00:00
|
|
|
/* Annotate slab for lockdep -- annotate the malloc caches */
|
|
|
|
init_lock_keys();
|
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
/* Done! */
|
|
|
|
slab_state = FULL;
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Register a cpu startup notifier callback that initializes
|
|
|
|
* cpu_cache_get for all new cpus
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
register_cpu_notifier(&cpucache_notifier);
|
|
|
|
|
2010-03-28 02:40:47 +00:00
|
|
|
#ifdef CONFIG_NUMA
|
|
|
|
/*
|
|
|
|
* Register a memory hotplug callback that initializes and frees
|
|
|
|
* nodelists.
|
|
|
|
*/
|
|
|
|
hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
|
|
|
|
#endif
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* The reap timers are started later, with a module init call: That part
|
|
|
|
* of the kernel is not yet operational.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init cpucache_init(void)
|
|
|
|
{
|
|
|
|
int cpu;
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Register the timers that return unneeded pages to the page allocator
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2005-09-09 20:03:32 +00:00
|
|
|
for_each_online_cpu(cpu)
|
2006-03-22 08:08:11 +00:00
|
|
|
start_cpu_timer(cpu);
|
slab: move FULL state transition to an initcall
During kmem_cache_init_late(), we transition to the LATE state,
and after some more work, to the FULL state, its last state
This is quite different from slub, that will only transition to
its last state (previously SYSFS), in a (late)initcall, after a lot
more of the kernel is ready.
This means that in slab, we have no way to taking actions dependent
on the initialization of other pieces of the kernel that are supposed
to start way after kmem_init_late(), such as cgroups initialization.
To achieve more consistency in this behavior, that patch only
transitions to the UP state in kmem_init_late. In my analysis,
setup_cpu_cache() should be happy to test for >= UP, instead of
== FULL. It also has passed some tests I've made.
We then only mark FULL state after the reap timers are in place,
meaning that no further setup is expected.
Signed-off-by: Glauber Costa <glommer@parallels.com>
Acked-by: Christoph Lameter <cl@linux.com>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2012-06-20 20:59:18 +00:00
|
|
|
|
|
|
|
/* Done! */
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = FULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
__initcall(cpucache_init);
|
|
|
|
|
2012-03-09 20:27:27 +00:00
|
|
|
static noinline void
|
|
|
|
slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
|
|
|
|
{
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
struct slab *slabp;
|
|
|
|
unsigned long flags;
|
|
|
|
int node;
|
|
|
|
|
|
|
|
printk(KERN_WARNING
|
|
|
|
"SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n",
|
|
|
|
nodeid, gfpflags);
|
|
|
|
printk(KERN_WARNING " cache: %s, object size: %d, order: %d\n",
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->name, cachep->size, cachep->gfporder);
|
2012-03-09 20:27:27 +00:00
|
|
|
|
|
|
|
for_each_online_node(node) {
|
|
|
|
unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
|
|
|
|
unsigned long active_slabs = 0, num_slabs = 0;
|
|
|
|
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&l3->list_lock, flags);
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list) {
|
|
|
|
active_objs += cachep->num;
|
|
|
|
active_slabs++;
|
|
|
|
}
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list) {
|
|
|
|
active_objs += slabp->inuse;
|
|
|
|
active_slabs++;
|
|
|
|
}
|
|
|
|
list_for_each_entry(slabp, &l3->slabs_free, list)
|
|
|
|
num_slabs++;
|
|
|
|
|
|
|
|
free_objects += l3->free_objects;
|
|
|
|
spin_unlock_irqrestore(&l3->list_lock, flags);
|
|
|
|
|
|
|
|
num_slabs += active_slabs;
|
|
|
|
num_objs = num_slabs * cachep->num;
|
|
|
|
printk(KERN_WARNING
|
|
|
|
" node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
|
|
|
|
node, active_slabs, num_slabs, active_objs, num_objs,
|
|
|
|
free_objects);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Interface to system's page allocator. No need to hold the cache-lock.
|
|
|
|
*
|
|
|
|
* If we requested dmaable memory, we will get it. Even if we
|
|
|
|
* did not request dmaable memory, we might get it, but that
|
|
|
|
* would be relatively rare and ignorable.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct page *page;
|
2006-06-23 09:03:17 +00:00
|
|
|
int nr_pages;
|
2005-04-16 22:20:36 +00:00
|
|
|
int i;
|
|
|
|
|
2006-04-11 05:52:56 +00:00
|
|
|
#ifndef CONFIG_MMU
|
2006-06-23 09:03:17 +00:00
|
|
|
/*
|
|
|
|
* Nommu uses slab's for process anonymous memory allocations, and thus
|
|
|
|
* requires __GFP_COMP to properly refcount higher order allocations
|
2006-04-11 05:52:56 +00:00
|
|
|
*/
|
2006-06-23 09:03:17 +00:00
|
|
|
flags |= __GFP_COMP;
|
2006-04-11 05:52:56 +00:00
|
|
|
#endif
|
2006-09-27 08:50:08 +00:00
|
|
|
|
2012-06-14 12:17:21 +00:00
|
|
|
flags |= cachep->allocflags;
|
2007-10-16 08:25:52 +00:00
|
|
|
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
|
|
|
|
flags |= __GFP_RECLAIMABLE;
|
2006-06-23 09:03:17 +00:00
|
|
|
|
2009-06-17 02:50:13 +00:00
|
|
|
page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
|
2012-03-09 20:27:27 +00:00
|
|
|
if (!page) {
|
|
|
|
if (!(flags & __GFP_NOWARN) && printk_ratelimit())
|
|
|
|
slab_out_of_memory(cachep, flags, nodeid);
|
2005-04-16 22:20:36 +00:00
|
|
|
return NULL;
|
2012-03-09 20:27:27 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-31 23:44:03 +00:00
|
|
|
/* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
if (unlikely(page->pfmemalloc))
|
|
|
|
pfmemalloc_active = true;
|
|
|
|
|
2006-06-23 09:03:17 +00:00
|
|
|
nr_pages = (1 << cachep->gfporder);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
|
2006-09-26 06:31:51 +00:00
|
|
|
add_zone_page_state(page_zone(page),
|
|
|
|
NR_SLAB_RECLAIMABLE, nr_pages);
|
|
|
|
else
|
|
|
|
add_zone_page_state(page_zone(page),
|
|
|
|
NR_SLAB_UNRECLAIMABLE, nr_pages);
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
for (i = 0; i < nr_pages; i++) {
|
2006-06-23 09:03:17 +00:00
|
|
|
__SetPageSlab(page + i);
|
2008-05-09 18:35:53 +00:00
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
if (page->pfmemalloc)
|
|
|
|
SetPageSlabPfmemalloc(page + i);
|
|
|
|
}
|
2012-12-18 22:22:50 +00:00
|
|
|
memcg_bind_pages(cachep, cachep->gfporder);
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
|
2008-11-25 15:55:53 +00:00
|
|
|
if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
|
|
|
|
kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid);
|
|
|
|
|
|
|
|
if (cachep->ctor)
|
|
|
|
kmemcheck_mark_uninitialized_pages(page, nr_pages);
|
|
|
|
else
|
|
|
|
kmemcheck_mark_unallocated_pages(page, nr_pages);
|
|
|
|
}
|
2008-05-09 18:35:53 +00:00
|
|
|
|
2006-06-23 09:03:17 +00:00
|
|
|
return page_address(page);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interface to system's page release.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static void kmem_freepages(struct kmem_cache *cachep, void *addr)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
unsigned long i = (1 << cachep->gfporder);
|
2005-04-16 22:20:36 +00:00
|
|
|
struct page *page = virt_to_page(addr);
|
|
|
|
const unsigned long nr_freed = i;
|
|
|
|
|
2008-11-25 15:55:53 +00:00
|
|
|
kmemcheck_free_shadow(page, cachep->gfporder);
|
2008-05-09 18:35:53 +00:00
|
|
|
|
2006-09-26 06:31:51 +00:00
|
|
|
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
|
|
|
|
sub_zone_page_state(page_zone(page),
|
|
|
|
NR_SLAB_RECLAIMABLE, nr_freed);
|
|
|
|
else
|
|
|
|
sub_zone_page_state(page_zone(page),
|
|
|
|
NR_SLAB_UNRECLAIMABLE, nr_freed);
|
2005-04-16 22:20:36 +00:00
|
|
|
while (i--) {
|
2006-03-22 08:08:02 +00:00
|
|
|
BUG_ON(!PageSlab(page));
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
__ClearPageSlabPfmemalloc(page);
|
2006-03-22 08:08:02 +00:00
|
|
|
__ClearPageSlab(page);
|
2005-04-16 22:20:36 +00:00
|
|
|
page++;
|
|
|
|
}
|
2012-12-18 22:22:50 +00:00
|
|
|
|
|
|
|
memcg_release_pages(cachep, cachep->gfporder);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (current->reclaim_state)
|
|
|
|
current->reclaim_state->reclaimed_slab += nr_freed;
|
2012-12-18 22:22:48 +00:00
|
|
|
free_memcg_kmem_pages((unsigned long)addr, cachep->gfporder);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void kmem_rcu_free(struct rcu_head *head)
|
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
struct slab_rcu *slab_rcu = (struct slab_rcu *)head;
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep = slab_rcu->cachep;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
kmem_freepages(cachep, slab_rcu->addr);
|
|
|
|
if (OFF_SLAB(cachep))
|
|
|
|
kmem_cache_free(cachep->slabp_cache, slab_rcu);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2006-02-01 11:05:50 +00:00
|
|
|
static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
|
2006-01-08 09:00:37 +00:00
|
|
|
unsigned long caller)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-06-13 15:24:58 +00:00
|
|
|
int size = cachep->object_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-01 11:05:42 +00:00
|
|
|
addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)];
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
if (size < 5 * sizeof(unsigned long))
|
2005-04-16 22:20:36 +00:00
|
|
|
return;
|
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
*addr++ = 0x12345678;
|
|
|
|
*addr++ = caller;
|
|
|
|
*addr++ = smp_processor_id();
|
|
|
|
size -= 3 * sizeof(unsigned long);
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
unsigned long *sptr = &caller;
|
|
|
|
unsigned long svalue;
|
|
|
|
|
|
|
|
while (!kstack_end(sptr)) {
|
|
|
|
svalue = *sptr++;
|
|
|
|
if (kernel_text_address(svalue)) {
|
2006-01-08 09:00:37 +00:00
|
|
|
*addr++ = svalue;
|
2005-04-16 22:20:36 +00:00
|
|
|
size -= sizeof(unsigned long);
|
|
|
|
if (size <= sizeof(unsigned long))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2006-01-08 09:00:37 +00:00
|
|
|
*addr++ = 0x87654321;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-06-13 15:24:58 +00:00
|
|
|
int size = cachep->object_size;
|
2006-02-01 11:05:42 +00:00
|
|
|
addr = &((char *)addr)[obj_offset(cachep)];
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
memset(addr, val, size);
|
2006-01-08 09:00:37 +00:00
|
|
|
*(unsigned char *)(addr + size - 1) = POISON_END;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_line(char *data, int offset, int limit)
|
|
|
|
{
|
|
|
|
int i;
|
2006-09-29 08:59:51 +00:00
|
|
|
unsigned char error = 0;
|
|
|
|
int bad_count = 0;
|
|
|
|
|
2011-07-29 16:22:13 +00:00
|
|
|
printk(KERN_ERR "%03x: ", offset);
|
2006-09-29 08:59:51 +00:00
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
if (data[offset + i] != POISON_FREE) {
|
|
|
|
error = data[offset + i];
|
|
|
|
bad_count++;
|
|
|
|
}
|
|
|
|
}
|
2011-07-29 16:22:13 +00:00
|
|
|
print_hex_dump(KERN_CONT, "", 0, 16, 1,
|
|
|
|
&data[offset], limit, 1);
|
2006-09-29 08:59:51 +00:00
|
|
|
|
|
|
|
if (bad_count == 1) {
|
|
|
|
error ^= POISON_FREE;
|
|
|
|
if (!(error & (error - 1))) {
|
|
|
|
printk(KERN_ERR "Single bit error detected. Probably "
|
|
|
|
"bad RAM.\n");
|
|
|
|
#ifdef CONFIG_X86
|
|
|
|
printk(KERN_ERR "Run memtest86+ or a similar memory "
|
|
|
|
"test tool.\n");
|
|
|
|
#else
|
|
|
|
printk(KERN_ERR "Run a memory test tool.\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i, size;
|
|
|
|
char *realobj;
|
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
printk(KERN_ERR "Redzone: 0x%llx/0x%llx.\n",
|
2006-03-22 08:08:11 +00:00
|
|
|
*dbg_redzone1(cachep, objp),
|
|
|
|
*dbg_redzone2(cachep, objp));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cachep->flags & SLAB_STORE_USER) {
|
|
|
|
printk(KERN_ERR "Last user: [<%p>]",
|
2006-03-22 08:08:11 +00:00
|
|
|
*dbg_userword(cachep, objp));
|
2005-04-16 22:20:36 +00:00
|
|
|
print_symbol("(%s)",
|
2006-03-22 08:08:11 +00:00
|
|
|
(unsigned long)*dbg_userword(cachep, objp));
|
2005-04-16 22:20:36 +00:00
|
|
|
printk("\n");
|
|
|
|
}
|
2006-02-01 11:05:42 +00:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2012-06-13 15:24:58 +00:00
|
|
|
size = cachep->object_size;
|
2006-01-08 09:00:37 +00:00
|
|
|
for (i = 0; i < size && lines; i += 16, lines--) {
|
2005-04-16 22:20:36 +00:00
|
|
|
int limit;
|
|
|
|
limit = 16;
|
2006-01-08 09:00:37 +00:00
|
|
|
if (i + limit > size)
|
|
|
|
limit = size - i;
|
2005-04-16 22:20:36 +00:00
|
|
|
dump_line(realobj, i, limit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void check_poison_obj(struct kmem_cache *cachep, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
char *realobj;
|
|
|
|
int size, i;
|
|
|
|
int lines = 0;
|
|
|
|
|
2006-02-01 11:05:42 +00:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2012-06-13 15:24:58 +00:00
|
|
|
size = cachep->object_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
for (i = 0; i < size; i++) {
|
2005-04-16 22:20:36 +00:00
|
|
|
char exp = POISON_FREE;
|
2006-01-08 09:00:37 +00:00
|
|
|
if (i == size - 1)
|
2005-04-16 22:20:36 +00:00
|
|
|
exp = POISON_END;
|
|
|
|
if (realobj[i] != exp) {
|
|
|
|
int limit;
|
|
|
|
/* Mismatch ! */
|
|
|
|
/* Print header */
|
|
|
|
if (lines == 0) {
|
2006-01-08 09:00:37 +00:00
|
|
|
printk(KERN_ERR
|
2011-11-15 23:03:52 +00:00
|
|
|
"Slab corruption (%s): %s start=%p, len=%d\n",
|
|
|
|
print_tainted(), cachep->name, realobj, size);
|
2005-04-16 22:20:36 +00:00
|
|
|
print_objinfo(cachep, objp, 0);
|
|
|
|
}
|
|
|
|
/* Hexdump the affected line */
|
2006-01-08 09:00:37 +00:00
|
|
|
i = (i / 16) * 16;
|
2005-04-16 22:20:36 +00:00
|
|
|
limit = 16;
|
2006-01-08 09:00:37 +00:00
|
|
|
if (i + limit > size)
|
|
|
|
limit = size - i;
|
2005-04-16 22:20:36 +00:00
|
|
|
dump_line(realobj, i, limit);
|
|
|
|
i += 16;
|
|
|
|
lines++;
|
|
|
|
/* Limit to 5 lines */
|
|
|
|
if (lines > 5)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lines != 0) {
|
|
|
|
/* Print some data about the neighboring objects, if they
|
|
|
|
* exist:
|
|
|
|
*/
|
2006-02-01 11:05:49 +00:00
|
|
|
struct slab *slabp = virt_to_slab(objp);
|
2006-03-22 08:08:10 +00:00
|
|
|
unsigned int objnr;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:08:10 +00:00
|
|
|
objnr = obj_to_index(cachep, slabp, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (objnr) {
|
2006-03-22 08:08:10 +00:00
|
|
|
objp = index_to_obj(cachep, slabp, objnr - 1);
|
2006-02-01 11:05:42 +00:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
|
2006-01-08 09:00:37 +00:00
|
|
|
realobj, size);
|
2005-04-16 22:20:36 +00:00
|
|
|
print_objinfo(cachep, objp, 2);
|
|
|
|
}
|
2006-01-08 09:00:37 +00:00
|
|
|
if (objnr + 1 < cachep->num) {
|
2006-03-22 08:08:10 +00:00
|
|
|
objp = index_to_obj(cachep, slabp, objnr + 1);
|
2006-02-01 11:05:42 +00:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
printk(KERN_ERR "Next obj: start=%p, len=%d\n",
|
2006-01-08 09:00:37 +00:00
|
|
|
realobj, size);
|
2005-04-16 22:20:36 +00:00
|
|
|
print_objinfo(cachep, objp, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-01 11:05:46 +00:00
|
|
|
#if DEBUG
|
2008-07-03 19:10:32 +00:00
|
|
|
static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slabp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < cachep->num; i++) {
|
2006-03-22 08:08:10 +00:00
|
|
|
void *objp = index_to_obj(cachep, slabp, i);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_POISON) {
|
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2012-06-13 15:24:57 +00:00
|
|
|
if (cachep->size % PAGE_SIZE == 0 &&
|
2006-03-22 08:08:11 +00:00
|
|
|
OFF_SLAB(cachep))
|
2006-01-08 09:00:37 +00:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->size / PAGE_SIZE, 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
|
|
|
check_poison_obj(cachep, objp);
|
|
|
|
#else
|
|
|
|
check_poison_obj(cachep, objp);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
|
|
|
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "start of a freed object "
|
2006-01-08 09:00:37 +00:00
|
|
|
"was overwritten");
|
2005-04-16 22:20:36 +00:00
|
|
|
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "end of a freed object "
|
2006-01-08 09:00:37 +00:00
|
|
|
"was overwritten");
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-01 11:05:46 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
#else
|
2008-07-03 19:10:32 +00:00
|
|
|
static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slabp)
|
2006-02-01 11:05:46 +00:00
|
|
|
{
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
|
2006-03-22 08:08:14 +00:00
|
|
|
/**
|
|
|
|
* slab_destroy - destroy and release all objects in a slab
|
|
|
|
* @cachep: cache pointer being destroyed
|
|
|
|
* @slabp: slab pointer being destroyed
|
|
|
|
*
|
2006-02-01 11:05:46 +00:00
|
|
|
* Destroy all the objs in a slab, and release the mem back to the system.
|
2006-03-22 08:08:11 +00:00
|
|
|
* Before calling the slab must have been unlinked from the cache. The
|
|
|
|
* cache-lock is not held/needed.
|
2006-02-01 11:05:46 +00:00
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
|
2006-02-01 11:05:46 +00:00
|
|
|
{
|
|
|
|
void *addr = slabp->s_mem - slabp->colouroff;
|
|
|
|
|
2008-07-03 19:10:32 +00:00
|
|
|
slab_destroy_debugcheck(cachep, slabp);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
|
|
|
|
struct slab_rcu *slab_rcu;
|
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
slab_rcu = (struct slab_rcu *)slabp;
|
2005-04-16 22:20:36 +00:00
|
|
|
slab_rcu->cachep = cachep;
|
|
|
|
slab_rcu->addr = addr;
|
|
|
|
call_rcu(&slab_rcu->head, kmem_rcu_free);
|
|
|
|
} else {
|
|
|
|
kmem_freepages(cachep, addr);
|
2006-07-13 12:44:38 +00:00
|
|
|
if (OFF_SLAB(cachep))
|
|
|
|
kmem_cache_free(cachep->slabp_cache, slabp);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-08 09:00:36 +00:00
|
|
|
/**
|
2006-02-01 11:05:52 +00:00
|
|
|
* calculate_slab_order - calculate size (page order) of slabs
|
|
|
|
* @cachep: pointer to the cache that is being created
|
|
|
|
* @size: size of objects to be created in this cache.
|
|
|
|
* @align: required alignment for the objects.
|
|
|
|
* @flags: slab allocation flags
|
|
|
|
*
|
|
|
|
* Also calculates the number of objects per slab.
|
2006-01-08 09:00:36 +00:00
|
|
|
*
|
|
|
|
* This could be made much more intelligent. For now, try to avoid using
|
|
|
|
* high order pages for slabs. When the gfp() functions are more friendly
|
|
|
|
* towards high-order requests, this should be changed.
|
|
|
|
*/
|
2006-03-22 08:08:11 +00:00
|
|
|
static size_t calculate_slab_order(struct kmem_cache *cachep,
|
2006-02-01 11:05:53 +00:00
|
|
|
size_t size, size_t align, unsigned long flags)
|
2006-01-08 09:00:36 +00:00
|
|
|
{
|
2006-06-02 13:44:58 +00:00
|
|
|
unsigned long offslab_limit;
|
2006-01-08 09:00:36 +00:00
|
|
|
size_t left_over = 0;
|
2006-03-07 01:44:43 +00:00
|
|
|
int gfporder;
|
2006-01-08 09:00:36 +00:00
|
|
|
|
2007-05-17 05:11:01 +00:00
|
|
|
for (gfporder = 0; gfporder <= KMALLOC_MAX_ORDER; gfporder++) {
|
2006-01-08 09:00:36 +00:00
|
|
|
unsigned int num;
|
|
|
|
size_t remainder;
|
|
|
|
|
2006-03-07 01:44:43 +00:00
|
|
|
cache_estimate(gfporder, size, align, flags, &remainder, &num);
|
2006-01-08 09:00:36 +00:00
|
|
|
if (!num)
|
|
|
|
continue;
|
2006-03-07 01:44:43 +00:00
|
|
|
|
2006-06-02 13:44:58 +00:00
|
|
|
if (flags & CFLGS_OFF_SLAB) {
|
|
|
|
/*
|
|
|
|
* Max number of objs-per-slab for caches which
|
|
|
|
* use off-slab slabs. Needed to avoid a possible
|
|
|
|
* looping condition in cache_grow().
|
|
|
|
*/
|
|
|
|
offslab_limit = size - sizeof(struct slab);
|
|
|
|
offslab_limit /= sizeof(kmem_bufctl_t);
|
|
|
|
|
|
|
|
if (num > offslab_limit)
|
|
|
|
break;
|
|
|
|
}
|
2006-01-08 09:00:36 +00:00
|
|
|
|
2006-03-07 01:44:43 +00:00
|
|
|
/* Found something acceptable - save it away */
|
2006-01-08 09:00:36 +00:00
|
|
|
cachep->num = num;
|
2006-03-07 01:44:43 +00:00
|
|
|
cachep->gfporder = gfporder;
|
2006-01-08 09:00:36 +00:00
|
|
|
left_over = remainder;
|
|
|
|
|
2006-03-08 18:33:05 +00:00
|
|
|
/*
|
|
|
|
* A VFS-reclaimable slab tends to have most allocations
|
|
|
|
* as GFP_NOFS and we really don't want to have to be allocating
|
|
|
|
* higher-order pages when we are unable to shrink dcache.
|
|
|
|
*/
|
|
|
|
if (flags & SLAB_RECLAIM_ACCOUNT)
|
|
|
|
break;
|
|
|
|
|
2006-01-08 09:00:36 +00:00
|
|
|
/*
|
|
|
|
* Large number of objects is good, but very large slabs are
|
|
|
|
* currently bad for the gfp()s.
|
|
|
|
*/
|
2011-10-19 05:09:24 +00:00
|
|
|
if (gfporder >= slab_max_order)
|
2006-01-08 09:00:36 +00:00
|
|
|
break;
|
|
|
|
|
2006-03-07 01:44:43 +00:00
|
|
|
/*
|
|
|
|
* Acceptable internal fragmentation?
|
|
|
|
*/
|
2006-03-22 08:08:11 +00:00
|
|
|
if (left_over * 8 <= (PAGE_SIZE << gfporder))
|
2006-01-08 09:00:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return left_over;
|
|
|
|
}
|
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
|
2006-03-22 08:08:11 +00:00
|
|
|
{
|
2012-07-06 20:25:11 +00:00
|
|
|
if (slab_state >= FULL)
|
2009-06-10 16:40:04 +00:00
|
|
|
return enable_cpucache(cachep, gfp);
|
2006-09-26 06:31:38 +00:00
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
if (slab_state == DOWN) {
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
2012-11-28 16:23:09 +00:00
|
|
|
* Note: Creation of first cache (kmem_cache).
|
|
|
|
* The setup_list3s is taken care
|
|
|
|
* of by the caller of __kmem_cache_create
|
|
|
|
*/
|
|
|
|
cachep->array[smp_processor_id()] = &initarray_generic.cache;
|
|
|
|
slab_state = PARTIAL;
|
|
|
|
} else if (slab_state == PARTIAL) {
|
|
|
|
/*
|
|
|
|
* Note: the second kmem_cache_create must create the cache
|
2006-03-22 08:08:11 +00:00
|
|
|
* that's used by kmalloc(24), otherwise the creation of
|
|
|
|
* further caches will BUG().
|
|
|
|
*/
|
|
|
|
cachep->array[smp_processor_id()] = &initarray_generic.cache;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the cache that's used by kmalloc(sizeof(kmem_list3)) is
|
2012-11-28 16:23:09 +00:00
|
|
|
* the second cache, then we need to set up all its list3s,
|
2006-03-22 08:08:11 +00:00
|
|
|
* otherwise the creation of further caches will BUG().
|
|
|
|
*/
|
|
|
|
set_up_list3s(cachep, SIZE_AC);
|
|
|
|
if (INDEX_AC == INDEX_L3)
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = PARTIAL_L3;
|
2006-03-22 08:08:11 +00:00
|
|
|
else
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = PARTIAL_ARRAYCACHE;
|
2006-03-22 08:08:11 +00:00
|
|
|
} else {
|
2012-11-28 16:23:09 +00:00
|
|
|
/* Remaining boot caches */
|
2006-03-22 08:08:11 +00:00
|
|
|
cachep->array[smp_processor_id()] =
|
2009-06-10 16:40:04 +00:00
|
|
|
kmalloc(sizeof(struct arraycache_init), gfp);
|
2006-03-22 08:08:11 +00:00
|
|
|
|
2012-07-06 20:25:11 +00:00
|
|
|
if (slab_state == PARTIAL_ARRAYCACHE) {
|
2006-03-22 08:08:11 +00:00
|
|
|
set_up_list3s(cachep, SIZE_L3);
|
2012-07-06 20:25:11 +00:00
|
|
|
slab_state = PARTIAL_L3;
|
2006-03-22 08:08:11 +00:00
|
|
|
} else {
|
|
|
|
int node;
|
2008-01-25 06:20:51 +00:00
|
|
|
for_each_online_node(node) {
|
2006-03-22 08:08:11 +00:00
|
|
|
cachep->nodelists[node] =
|
|
|
|
kmalloc_node(sizeof(struct kmem_list3),
|
2009-06-12 11:56:09 +00:00
|
|
|
gfp, node);
|
2006-03-22 08:08:11 +00:00
|
|
|
BUG_ON(!cachep->nodelists[node]);
|
|
|
|
kmem_list3_init(cachep->nodelists[node]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
cachep->nodelists[numa_mem_id()]->next_reap =
|
2006-03-22 08:08:11 +00:00
|
|
|
jiffies + REAPTIMEOUT_LIST3 +
|
|
|
|
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
|
|
|
|
|
|
|
|
cpu_cache_get(cachep)->avail = 0;
|
|
|
|
cpu_cache_get(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
|
|
|
|
cpu_cache_get(cachep)->batchcount = 1;
|
|
|
|
cpu_cache_get(cachep)->touched = 0;
|
|
|
|
cachep->batchcount = 1;
|
|
|
|
cachep->limit = BOOT_CPUCACHE_ENTRIES;
|
2006-09-26 06:31:38 +00:00
|
|
|
return 0;
|
2006-03-22 08:08:11 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
2012-07-06 20:25:10 +00:00
|
|
|
* __kmem_cache_create - Create a cache.
|
2012-11-07 01:10:10 +00:00
|
|
|
* @cachep: cache management descriptor
|
2005-04-16 22:20:36 +00:00
|
|
|
* @flags: SLAB flags
|
|
|
|
*
|
|
|
|
* Returns a ptr to the cache on success, NULL on failure.
|
|
|
|
* Cannot be called within a int, but can be interrupted.
|
2007-07-20 01:11:58 +00:00
|
|
|
* The @ctor is run when new pages are allocated by the cache.
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* The flags are
|
|
|
|
*
|
|
|
|
* %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
|
|
|
|
* to catch references to uninitialised memory.
|
|
|
|
*
|
|
|
|
* %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check
|
|
|
|
* for buffer overruns.
|
|
|
|
*
|
|
|
|
* %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware
|
|
|
|
* cacheline. This can be beneficial if you're counting cycles as closely
|
|
|
|
* as davem.
|
|
|
|
*/
|
2012-09-05 00:20:34 +00:00
|
|
|
int
|
2012-09-04 23:18:33 +00:00
|
|
|
__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
size_t left_over, slab_size, ralign;
|
2009-06-10 16:40:04 +00:00
|
|
|
gfp_t gfp;
|
2012-09-05 00:20:34 +00:00
|
|
|
int err;
|
2012-09-04 23:18:33 +00:00
|
|
|
size_t size = cachep->size;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
#if FORCED_DEBUG
|
|
|
|
/*
|
|
|
|
* Enable redzoning and last user accounting, except for caches with
|
|
|
|
* large objects, if the increased size would increase the object size
|
|
|
|
* above the next power of two: caches with object sizes just above a
|
|
|
|
* power of two have a significant amount of internal fragmentation.
|
|
|
|
*/
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
|
|
|
|
2 * sizeof(unsigned long long)))
|
2006-01-08 09:00:37 +00:00
|
|
|
flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!(flags & SLAB_DESTROY_BY_RCU))
|
|
|
|
flags |= SLAB_POISON;
|
|
|
|
#endif
|
|
|
|
if (flags & SLAB_DESTROY_BY_RCU)
|
|
|
|
BUG_ON(flags & SLAB_POISON);
|
|
|
|
#endif
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Check that size is in terms of words. This is needed to avoid
|
2005-04-16 22:20:36 +00:00
|
|
|
* unaligned accesses for some archs when redzoning is used, and makes
|
|
|
|
* sure any on-slab bufctl's are also correctly aligned.
|
|
|
|
*/
|
2006-01-08 09:00:37 +00:00
|
|
|
if (size & (BYTES_PER_WORD - 1)) {
|
|
|
|
size += (BYTES_PER_WORD - 1);
|
|
|
|
size &= ~(BYTES_PER_WORD - 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-26 06:31:25 +00:00
|
|
|
/*
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
* Redzoning and user store require word alignment or possibly larger.
|
|
|
|
* Note this will be overridden by architecture or caller mandated
|
|
|
|
* alignment if either is greater than BYTES_PER_WORD.
|
2006-09-26 06:31:25 +00:00
|
|
|
*/
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
if (flags & SLAB_STORE_USER)
|
|
|
|
ralign = BYTES_PER_WORD;
|
|
|
|
|
|
|
|
if (flags & SLAB_RED_ZONE) {
|
|
|
|
ralign = REDZONE_ALIGN;
|
|
|
|
/* If redzoning, ensure that the second redzone is suitably
|
|
|
|
* aligned, by adjusting the object size accordingly. */
|
|
|
|
size += REDZONE_ALIGN - 1;
|
|
|
|
size &= ~(REDZONE_ALIGN - 1);
|
|
|
|
}
|
2006-09-26 06:31:25 +00:00
|
|
|
|
2006-12-07 04:32:11 +00:00
|
|
|
/* 3) caller mandated alignment */
|
2012-09-04 23:18:33 +00:00
|
|
|
if (ralign < cachep->align) {
|
|
|
|
ralign = cachep->align;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2011-02-14 15:46:21 +00:00
|
|
|
/* disable debug if necessary */
|
|
|
|
if (ralign > __alignof__(unsigned long long))
|
2006-12-07 04:32:11 +00:00
|
|
|
flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
2006-09-26 06:31:25 +00:00
|
|
|
* 4) Store it.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2012-09-04 23:18:33 +00:00
|
|
|
cachep->align = ralign;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-10 16:40:04 +00:00
|
|
|
if (slab_is_available())
|
|
|
|
gfp = GFP_KERNEL;
|
|
|
|
else
|
|
|
|
gfp = GFP_NOWAIT;
|
|
|
|
|
2012-11-28 16:23:01 +00:00
|
|
|
setup_nodelists_pointer(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
#if DEBUG
|
|
|
|
|
2006-09-26 06:31:25 +00:00
|
|
|
/*
|
|
|
|
* Both debugging options require word-alignment which is calculated
|
|
|
|
* into align above.
|
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
if (flags & SLAB_RED_ZONE) {
|
|
|
|
/* add space for red zone words */
|
2011-02-14 15:46:21 +00:00
|
|
|
cachep->obj_offset += sizeof(unsigned long long);
|
|
|
|
size += 2 * sizeof(unsigned long long);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
if (flags & SLAB_STORE_USER) {
|
2006-09-26 06:31:25 +00:00
|
|
|
/* user store requires one word storage behind the end of
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
* the real object. But if the second red zone needs to be
|
|
|
|
* aligned to 64 bits, we must allow that much space.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
Fix slab redzone alignment
Commit b46b8f19c9cd435ecac4d9d12b39d78c137ecd66 fixed a couple of bugs
by switching the redzone to 64 bits. Unfortunately, it neglected to
ensure that the _second_ redzone, after the slab object, is aligned
correctly. This caused illegal instruction faults on sparc32, which for
some reason not entirely clear to me are not trapped and fixed up.
Two things need to be done to fix this:
- increase the object size, rounding up to alignof(long long) so
that the second redzone can be aligned correctly.
- If SLAB_STORE_USER is set but alignof(long long)==8, allow a
full 64 bits of space for the user word at the end of the buffer,
even though we may not _use_ the whole 64 bits.
This patch should be a no-op on any 64-bit architecture or any 32-bit
architecture where alignof(long long) == 4. Of the others, it's tested
on ppc32 by myself and a very similar patch was tested on sparc32 by
Mark Fortescue, who reported the new problem.
Also, fix the conditions for FORCED_DEBUG, which hadn't been adjusted to
the new sizes. Again noticed by Mark.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-05 01:26:44 +00:00
|
|
|
if (flags & SLAB_RED_ZONE)
|
|
|
|
size += REDZONE_ALIGN;
|
|
|
|
else
|
|
|
|
size += BYTES_PER_WORD;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
|
2006-01-08 09:00:37 +00:00
|
|
|
if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
|
2012-09-30 08:28:25 +00:00
|
|
|
&& cachep->object_size > cache_line_size()
|
|
|
|
&& ALIGN(size, cachep->align) < PAGE_SIZE) {
|
|
|
|
cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
|
2005-04-16 22:20:36 +00:00
|
|
|
size = PAGE_SIZE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2006-06-23 09:03:46 +00:00
|
|
|
/*
|
|
|
|
* Determine if the slab management is 'on' or 'off' slab.
|
|
|
|
* (bootstrapping cannot cope with offslab caches so don't do
|
2009-10-28 13:33:08 +00:00
|
|
|
* it too early on. Always use on-slab management when
|
|
|
|
* SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
|
2006-06-23 09:03:46 +00:00
|
|
|
*/
|
2009-10-28 13:33:08 +00:00
|
|
|
if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
|
|
|
|
!(flags & SLAB_NOLEAKTRACE))
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Size is large, assume best to place the slab management obj
|
|
|
|
* off-slab (should allow better packing of objs).
|
|
|
|
*/
|
|
|
|
flags |= CFLGS_OFF_SLAB;
|
|
|
|
|
2012-09-04 23:18:33 +00:00
|
|
|
size = ALIGN(size, cachep->align);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-04 23:18:33 +00:00
|
|
|
left_over = calculate_slab_order(cachep, size, cachep->align, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-04 23:18:33 +00:00
|
|
|
if (!cachep->num)
|
2012-09-05 00:20:34 +00:00
|
|
|
return -E2BIG;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
|
2012-09-04 23:18:33 +00:00
|
|
|
+ sizeof(struct slab), cachep->align);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the slab has been placed off-slab, and we have enough space then
|
|
|
|
* move it on-slab. This is at the expense of any extra colouring.
|
|
|
|
*/
|
|
|
|
if (flags & CFLGS_OFF_SLAB && left_over >= slab_size) {
|
|
|
|
flags &= ~CFLGS_OFF_SLAB;
|
|
|
|
left_over -= slab_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & CFLGS_OFF_SLAB) {
|
|
|
|
/* really off slab. No need for manual alignment */
|
2006-01-08 09:00:37 +00:00
|
|
|
slab_size =
|
|
|
|
cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
|
2009-05-21 19:28:22 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_PAGE_POISONING
|
|
|
|
/* If we're going to use the generic kernel_map_pages()
|
|
|
|
* poisoning, then it's going to smash the contents of
|
|
|
|
* the redzone and userword anyhow, so switch them off.
|
|
|
|
*/
|
|
|
|
if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
|
|
|
|
flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
|
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cachep->colour_off = cache_line_size();
|
|
|
|
/* Offset must be a multiple of the alignment. */
|
2012-09-04 23:18:33 +00:00
|
|
|
if (cachep->colour_off < cachep->align)
|
|
|
|
cachep->colour_off = cachep->align;
|
2006-01-08 09:00:37 +00:00
|
|
|
cachep->colour = left_over / cachep->colour_off;
|
2005-04-16 22:20:36 +00:00
|
|
|
cachep->slab_size = slab_size;
|
|
|
|
cachep->flags = flags;
|
2012-06-14 12:17:21 +00:00
|
|
|
cachep->allocflags = 0;
|
2007-02-10 09:43:10 +00:00
|
|
|
if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
|
2012-06-14 12:17:21 +00:00
|
|
|
cachep->allocflags |= GFP_DMA;
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->size = size;
|
2006-12-13 08:34:27 +00:00
|
|
|
cachep->reciprocal_buffer_size = reciprocal_value(size);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-09-26 06:31:34 +00:00
|
|
|
if (flags & CFLGS_OFF_SLAB) {
|
2005-09-10 07:26:36 +00:00
|
|
|
cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
|
2006-09-26 06:31:34 +00:00
|
|
|
/*
|
|
|
|
* This is a possibility for one of the malloc_sizes caches.
|
|
|
|
* But since we go off slab only for object size greater than
|
|
|
|
* PAGE_SIZE/8, and malloc_sizes gets created in ascending order,
|
|
|
|
* this should not happen at all.
|
|
|
|
* But leave a BUG_ON for some lucky dude.
|
|
|
|
*/
|
2007-07-17 11:03:22 +00:00
|
|
|
BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
|
2006-09-26 06:31:34 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-05 00:20:34 +00:00
|
|
|
err = setup_cpu_cache(cachep, gfp);
|
|
|
|
if (err) {
|
2012-09-04 23:38:33 +00:00
|
|
|
__kmem_cache_shutdown(cachep);
|
2012-09-05 00:20:34 +00:00
|
|
|
return err;
|
2006-09-26 06:31:38 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-07-22 13:26:05 +00:00
|
|
|
if (flags & SLAB_DEBUG_OBJECTS) {
|
|
|
|
/*
|
|
|
|
* Would deadlock through slab_destroy()->call_rcu()->
|
|
|
|
* debug_object_activate()->kmem_cache_alloc().
|
|
|
|
*/
|
|
|
|
WARN_ON_ONCE(flags & SLAB_DESTROY_BY_RCU);
|
|
|
|
|
|
|
|
slab_set_debugobj_lock_classes(cachep);
|
2012-12-18 22:22:31 +00:00
|
|
|
} else if (!OFF_SLAB(cachep) && !(flags & SLAB_DESTROY_BY_RCU))
|
|
|
|
on_slab_lock_classes(cachep);
|
2011-07-22 13:26:05 +00:00
|
|
|
|
2012-09-05 00:20:34 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
static void check_irq_off(void)
|
|
|
|
{
|
|
|
|
BUG_ON(!irqs_disabled());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void check_irq_on(void)
|
|
|
|
{
|
|
|
|
BUG_ON(irqs_disabled());
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void check_spinlock_acquired(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
check_irq_off();
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
assert_spin_locked(&cachep->nodelists[numa_mem_id()]->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
}
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
check_irq_off();
|
|
|
|
assert_spin_locked(&cachep->nodelists[node]->list_lock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#else
|
|
|
|
#define check_irq_off() do { } while(0)
|
|
|
|
#define check_irq_on() do { } while(0)
|
|
|
|
#define check_spinlock_acquired(x) do { } while(0)
|
2005-09-09 20:03:32 +00:00
|
|
|
#define check_spinlock_acquired_node(x, y) do { } while(0)
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
|
2006-03-22 08:09:06 +00:00
|
|
|
static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
|
|
|
|
struct array_cache *ac,
|
|
|
|
int force, int node);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
static void do_drain(void *arg)
|
|
|
|
{
|
2006-03-22 08:08:11 +00:00
|
|
|
struct kmem_cache *cachep = arg;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct array_cache *ac;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int node = numa_mem_id();
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
check_irq_off();
|
2006-02-01 11:05:49 +00:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-09-23 04:44:02 +00:00
|
|
|
spin_lock(&cachep->nodelists[node]->list_lock);
|
|
|
|
free_block(cachep, ac->entry, ac->avail, node);
|
|
|
|
spin_unlock(&cachep->nodelists[node]->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
ac->avail = 0;
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void drain_cpu_caches(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3;
|
|
|
|
int node;
|
|
|
|
|
2008-05-09 07:39:44 +00:00
|
|
|
on_each_cpu(do_drain, cachep, 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
check_irq_on();
|
2006-01-08 09:00:37 +00:00
|
|
|
for_each_online_node(node) {
|
2005-09-09 20:03:32 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-05-15 18:41:00 +00:00
|
|
|
if (l3 && l3->alien)
|
|
|
|
drain_alien_cache(cachep, l3->alien);
|
|
|
|
}
|
|
|
|
|
|
|
|
for_each_online_node(node) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (l3)
|
2006-03-22 08:09:06 +00:00
|
|
|
drain_array(cachep, l3, l3->shared, 1, node);
|
2005-09-09 20:03:32 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
/*
|
|
|
|
* Remove slabs from the list of free slabs.
|
|
|
|
* Specify the number of slabs to drain in tofree.
|
|
|
|
*
|
|
|
|
* Returns the actual number of slabs released.
|
|
|
|
*/
|
|
|
|
static int drain_freelist(struct kmem_cache *cache,
|
|
|
|
struct kmem_list3 *l3, int tofree)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-06-30 08:55:45 +00:00
|
|
|
struct list_head *p;
|
|
|
|
int nr_freed;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
nr_freed = 0;
|
|
|
|
while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
2005-09-09 20:03:32 +00:00
|
|
|
p = l3->slabs_free.prev;
|
2006-06-30 08:55:45 +00:00
|
|
|
if (p == &l3->slabs_free) {
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
slabp = list_entry(p, struct slab, list);
|
2005-04-16 22:20:36 +00:00
|
|
|
#if DEBUG
|
2006-04-02 11:49:25 +00:00
|
|
|
BUG_ON(slabp->inuse);
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
list_del(&slabp->list);
|
2006-06-30 08:55:45 +00:00
|
|
|
/*
|
|
|
|
* Safe to drop the lock. The slab is no longer linked
|
|
|
|
* to the cache.
|
|
|
|
*/
|
|
|
|
l3->free_objects -= cache->num;
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2006-06-30 08:55:45 +00:00
|
|
|
slab_destroy(cache, slabp);
|
|
|
|
nr_freed++;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-06-30 08:55:45 +00:00
|
|
|
out:
|
|
|
|
return nr_freed;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
/* Called with slab_mutex held to protect against cpu hotplug */
|
2006-02-01 11:05:50 +00:00
|
|
|
static int __cache_shrink(struct kmem_cache *cachep)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
int ret = 0, i = 0;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
|
|
|
|
drain_cpu_caches(cachep);
|
|
|
|
|
|
|
|
check_irq_on();
|
|
|
|
for_each_online_node(i) {
|
|
|
|
l3 = cachep->nodelists[i];
|
2006-06-30 08:55:45 +00:00
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drain_freelist(cachep, l3, l3->free_objects);
|
|
|
|
|
|
|
|
ret += !list_empty(&l3->slabs_full) ||
|
|
|
|
!list_empty(&l3->slabs_partial);
|
2005-09-09 20:03:32 +00:00
|
|
|
}
|
|
|
|
return (ret ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* kmem_cache_shrink - Shrink a cache.
|
|
|
|
* @cachep: The cache to shrink.
|
|
|
|
*
|
|
|
|
* Releases as many slabs as possible for a cache.
|
|
|
|
* To help debugging, a zero exit status indicates all slabs were released.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
int kmem_cache_shrink(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
[PATCH] mm: slab: eliminate lock_cpu_hotplug from slab
Here's an attempt towards doing away with lock_cpu_hotplug in the slab
subsystem. This approach also fixes a bug which shows up when cpus are
being offlined/onlined and slab caches are being tuned simultaneously.
http://marc.theaimsgroup.com/?l=linux-kernel&m=116098888100481&w=2
The patch has been stress tested overnight on a 2 socket 4 core AMD box with
repeated cpu online and offline, while dbench and kernbench process are
running, and slab caches being tuned at the same time.
There were no lockdep warnings either. (This test on 2,6.18 as 2.6.19-rc
crashes at __drain_pages
http://marc.theaimsgroup.com/?l=linux-kernel&m=116172164217678&w=2 )
The approach here is to hold cache_chain_mutex from CPU_UP_PREPARE until
CPU_ONLINE (similar in approach as worqueue_mutex) . Slab code sensitive
to cpu_online_map (kmem_cache_create, kmem_cache_destroy, slabinfo_write,
__cache_shrink) is already serialized with cache_chain_mutex. (This patch
lengthens cache_chain_mutex hold time at kmem_cache_destroy to cover this).
This patch also takes the cache_chain_sem at kmem_cache_shrink to protect
sanity of cpu_online_map at __cache_shrink, as viewed by slab.
(kmem_cache_shrink->__cache_shrink->drain_cpu_caches). But, really,
kmem_cache_shrink is used at just one place in the acpi subsystem! Do we
really need to keep kmem_cache_shrink at all?
Another note. Looks like a cpu hotplug event can send CPU_UP_CANCELED to
a registered subsystem even if the subsystem did not receive CPU_UP_PREPARE.
This could be due to a subsystem registered for notification earlier than
the current subsystem crapping out with NOTIFY_BAD. Badness can occur with
in the CPU_UP_CANCELED code path at slab if this happens (The same would
apply for workqueue.c as well). To overcome this, we might have to use either
a) a per subsystem flag and avoid handling of CPU_UP_CANCELED, or
b) Use a special notifier events like LOCK_ACQUIRE/RELEASE as Gautham was
using in his experiments, or
c) Do not send CPU_UP_CANCELED to a subsystem which did not receive
CPU_UP_PREPARE.
I would prefer c).
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 04:32:14 +00:00
|
|
|
int ret;
|
2006-04-02 11:49:25 +00:00
|
|
|
BUG_ON(!cachep || in_interrupt());
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-01-25 20:08:02 +00:00
|
|
|
get_online_cpus();
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
[PATCH] mm: slab: eliminate lock_cpu_hotplug from slab
Here's an attempt towards doing away with lock_cpu_hotplug in the slab
subsystem. This approach also fixes a bug which shows up when cpus are
being offlined/onlined and slab caches are being tuned simultaneously.
http://marc.theaimsgroup.com/?l=linux-kernel&m=116098888100481&w=2
The patch has been stress tested overnight on a 2 socket 4 core AMD box with
repeated cpu online and offline, while dbench and kernbench process are
running, and slab caches being tuned at the same time.
There were no lockdep warnings either. (This test on 2,6.18 as 2.6.19-rc
crashes at __drain_pages
http://marc.theaimsgroup.com/?l=linux-kernel&m=116172164217678&w=2 )
The approach here is to hold cache_chain_mutex from CPU_UP_PREPARE until
CPU_ONLINE (similar in approach as worqueue_mutex) . Slab code sensitive
to cpu_online_map (kmem_cache_create, kmem_cache_destroy, slabinfo_write,
__cache_shrink) is already serialized with cache_chain_mutex. (This patch
lengthens cache_chain_mutex hold time at kmem_cache_destroy to cover this).
This patch also takes the cache_chain_sem at kmem_cache_shrink to protect
sanity of cpu_online_map at __cache_shrink, as viewed by slab.
(kmem_cache_shrink->__cache_shrink->drain_cpu_caches). But, really,
kmem_cache_shrink is used at just one place in the acpi subsystem! Do we
really need to keep kmem_cache_shrink at all?
Another note. Looks like a cpu hotplug event can send CPU_UP_CANCELED to
a registered subsystem even if the subsystem did not receive CPU_UP_PREPARE.
This could be due to a subsystem registered for notification earlier than
the current subsystem crapping out with NOTIFY_BAD. Badness can occur with
in the CPU_UP_CANCELED code path at slab if this happens (The same would
apply for workqueue.c as well). To overcome this, we might have to use either
a) a per subsystem flag and avoid handling of CPU_UP_CANCELED, or
b) Use a special notifier events like LOCK_ACQUIRE/RELEASE as Gautham was
using in his experiments, or
c) Do not send CPU_UP_CANCELED to a subsystem which did not receive
CPU_UP_PREPARE.
I would prefer c).
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 04:32:14 +00:00
|
|
|
ret = __cache_shrink(cachep);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2008-01-25 20:08:02 +00:00
|
|
|
put_online_cpus();
|
[PATCH] mm: slab: eliminate lock_cpu_hotplug from slab
Here's an attempt towards doing away with lock_cpu_hotplug in the slab
subsystem. This approach also fixes a bug which shows up when cpus are
being offlined/onlined and slab caches are being tuned simultaneously.
http://marc.theaimsgroup.com/?l=linux-kernel&m=116098888100481&w=2
The patch has been stress tested overnight on a 2 socket 4 core AMD box with
repeated cpu online and offline, while dbench and kernbench process are
running, and slab caches being tuned at the same time.
There were no lockdep warnings either. (This test on 2,6.18 as 2.6.19-rc
crashes at __drain_pages
http://marc.theaimsgroup.com/?l=linux-kernel&m=116172164217678&w=2 )
The approach here is to hold cache_chain_mutex from CPU_UP_PREPARE until
CPU_ONLINE (similar in approach as worqueue_mutex) . Slab code sensitive
to cpu_online_map (kmem_cache_create, kmem_cache_destroy, slabinfo_write,
__cache_shrink) is already serialized with cache_chain_mutex. (This patch
lengthens cache_chain_mutex hold time at kmem_cache_destroy to cover this).
This patch also takes the cache_chain_sem at kmem_cache_shrink to protect
sanity of cpu_online_map at __cache_shrink, as viewed by slab.
(kmem_cache_shrink->__cache_shrink->drain_cpu_caches). But, really,
kmem_cache_shrink is used at just one place in the acpi subsystem! Do we
really need to keep kmem_cache_shrink at all?
Another note. Looks like a cpu hotplug event can send CPU_UP_CANCELED to
a registered subsystem even if the subsystem did not receive CPU_UP_PREPARE.
This could be due to a subsystem registered for notification earlier than
the current subsystem crapping out with NOTIFY_BAD. Badness can occur with
in the CPU_UP_CANCELED code path at slab if this happens (The same would
apply for workqueue.c as well). To overcome this, we might have to use either
a) a per subsystem flag and avoid handling of CPU_UP_CANCELED, or
b) Use a special notifier events like LOCK_ACQUIRE/RELEASE as Gautham was
using in his experiments, or
c) Do not send CPU_UP_CANCELED to a subsystem which did not receive
CPU_UP_PREPARE.
I would prefer c).
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 04:32:14 +00:00
|
|
|
return ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_shrink);
|
|
|
|
|
2012-09-04 23:18:33 +00:00
|
|
|
int __kmem_cache_shutdown(struct kmem_cache *cachep)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-09-04 23:38:33 +00:00
|
|
|
int i;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
int rc = __cache_shrink(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-04 23:38:33 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-04 23:38:33 +00:00
|
|
|
for_each_online_cpu(i)
|
|
|
|
kfree(cachep->array[i]);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-09-04 23:38:33 +00:00
|
|
|
/* NUMA: free the list3 structures */
|
|
|
|
for_each_online_node(i) {
|
|
|
|
l3 = cachep->nodelists[i];
|
|
|
|
if (l3) {
|
|
|
|
kfree(l3->shared);
|
|
|
|
free_alien_cache(l3->alien);
|
|
|
|
kfree(l3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-09-26 06:31:34 +00:00
|
|
|
/*
|
|
|
|
* Get the memory for a slab management obj.
|
|
|
|
* For a slab cache when the slab descriptor is off-slab, slab descriptors
|
|
|
|
* always come from malloc_sizes caches. The slab descriptor cannot
|
|
|
|
* come from the same cache which is getting created because,
|
|
|
|
* when we are searching for an appropriate cache for these
|
|
|
|
* descriptors in kmem_cache_create, we search through the malloc_sizes array.
|
|
|
|
* If we are creating a malloc_sizes cache here it would not be visible to
|
|
|
|
* kmem_find_general_cachep till the initialization is complete.
|
|
|
|
* Hence we cannot have slabp_cache same as the original cache.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
|
2006-04-11 05:52:53 +00:00
|
|
|
int colour_off, gfp_t local_flags,
|
|
|
|
int nodeid)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct slab *slabp;
|
2006-01-08 09:00:37 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (OFF_SLAB(cachep)) {
|
|
|
|
/* Slab management obj is off-slab. */
|
2006-04-11 05:52:53 +00:00
|
|
|
slabp = kmem_cache_alloc_node(cachep->slabp_cache,
|
2008-11-26 08:01:31 +00:00
|
|
|
local_flags, nodeid);
|
2009-06-11 12:22:40 +00:00
|
|
|
/*
|
|
|
|
* If the first object in the slab is leaked (it's allocated
|
|
|
|
* but no one has a reference to it), we want to make sure
|
|
|
|
* kmemleak does not treat the ->s_mem pointer as a reference
|
|
|
|
* to the object. Otherwise we will not report the leak.
|
|
|
|
*/
|
2009-10-28 13:33:09 +00:00
|
|
|
kmemleak_scan_area(&slabp->list, sizeof(struct list_head),
|
|
|
|
local_flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!slabp)
|
|
|
|
return NULL;
|
|
|
|
} else {
|
2006-01-08 09:00:37 +00:00
|
|
|
slabp = objp + colour_off;
|
2005-04-16 22:20:36 +00:00
|
|
|
colour_off += cachep->slab_size;
|
|
|
|
}
|
|
|
|
slabp->inuse = 0;
|
|
|
|
slabp->colouroff = colour_off;
|
2006-01-08 09:00:37 +00:00
|
|
|
slabp->s_mem = objp + colour_off;
|
2006-04-11 05:52:53 +00:00
|
|
|
slabp->nodeid = nodeid;
|
2008-02-10 10:21:54 +00:00
|
|
|
slabp->free = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
return slabp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
|
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
return (kmem_bufctl_t *) (slabp + 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void cache_init_objs(struct kmem_cache *cachep,
|
2007-05-17 05:10:57 +00:00
|
|
|
struct slab *slabp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < cachep->num; i++) {
|
2006-03-22 08:08:10 +00:00
|
|
|
void *objp = index_to_obj(cachep, slabp, i);
|
2005-04-16 22:20:36 +00:00
|
|
|
#if DEBUG
|
|
|
|
/* need to poison the objs? */
|
|
|
|
if (cachep->flags & SLAB_POISON)
|
|
|
|
poison_obj(cachep, objp, POISON_FREE);
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
|
|
|
*dbg_userword(cachep, objp) = NULL;
|
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
|
|
|
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
|
|
|
|
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
|
|
|
|
}
|
|
|
|
/*
|
2006-03-22 08:08:11 +00:00
|
|
|
* Constructors are not allowed to allocate memory from the same
|
|
|
|
* cache which they are a constructor for. Otherwise, deadlock.
|
|
|
|
* They must also be threaded.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
|
2008-07-26 02:45:34 +00:00
|
|
|
cachep->ctor(objp + obj_offset(cachep));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
|
|
|
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "constructor overwrote the"
|
2006-01-08 09:00:37 +00:00
|
|
|
" end of an object");
|
2005-04-16 22:20:36 +00:00
|
|
|
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "constructor overwrote the"
|
2006-01-08 09:00:37 +00:00
|
|
|
" start of an object");
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2012-06-13 15:24:57 +00:00
|
|
|
if ((cachep->size % PAGE_SIZE) == 0 &&
|
2006-03-22 08:08:11 +00:00
|
|
|
OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
|
2006-01-08 09:00:37 +00:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->size / PAGE_SIZE, 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
#else
|
|
|
|
if (cachep->ctor)
|
2008-07-26 02:45:34 +00:00
|
|
|
cachep->ctor(objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
2006-01-08 09:00:37 +00:00
|
|
|
slab_bufctl(slabp)[i] = i + 1;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-01-08 09:00:37 +00:00
|
|
|
slab_bufctl(slabp)[i - 1] = BUFCTL_END;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-02-10 09:43:10 +00:00
|
|
|
if (CONFIG_ZONE_DMA_FLAG) {
|
|
|
|
if (flags & GFP_DMA)
|
2012-06-14 12:17:21 +00:00
|
|
|
BUG_ON(!(cachep->allocflags & GFP_DMA));
|
2007-02-10 09:43:10 +00:00
|
|
|
else
|
2012-06-14 12:17:21 +00:00
|
|
|
BUG_ON(cachep->allocflags & GFP_DMA);
|
2007-02-10 09:43:10 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp,
|
|
|
|
int nodeid)
|
2006-02-01 11:05:47 +00:00
|
|
|
{
|
2006-03-22 08:08:10 +00:00
|
|
|
void *objp = index_to_obj(cachep, slabp, slabp->free);
|
2006-02-01 11:05:47 +00:00
|
|
|
kmem_bufctl_t next;
|
|
|
|
|
|
|
|
slabp->inuse++;
|
|
|
|
next = slab_bufctl(slabp)[slabp->free];
|
|
|
|
#if DEBUG
|
|
|
|
slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
|
|
|
|
WARN_ON(slabp->nodeid != nodeid);
|
|
|
|
#endif
|
|
|
|
slabp->free = next;
|
|
|
|
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp,
|
|
|
|
void *objp, int nodeid)
|
2006-02-01 11:05:47 +00:00
|
|
|
{
|
2006-03-22 08:08:10 +00:00
|
|
|
unsigned int objnr = obj_to_index(cachep, slabp, objp);
|
2006-02-01 11:05:47 +00:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
/* Verify that the slab belongs to the intended node */
|
|
|
|
WARN_ON(slabp->nodeid != nodeid);
|
|
|
|
|
2006-03-25 11:06:39 +00:00
|
|
|
if (slab_bufctl(slabp)[objnr] + 1 <= SLAB_LIMIT + 1) {
|
2006-02-01 11:05:47 +00:00
|
|
|
printk(KERN_ERR "slab: double free detected in cache "
|
2006-03-22 08:08:11 +00:00
|
|
|
"'%s', objp %p\n", cachep->name, objp);
|
2006-02-01 11:05:47 +00:00
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
slab_bufctl(slabp)[objnr] = slabp->free;
|
|
|
|
slabp->free = objnr;
|
|
|
|
slabp->inuse--;
|
|
|
|
}
|
|
|
|
|
2006-06-23 09:03:07 +00:00
|
|
|
/*
|
|
|
|
* Map pages beginning at addr to the given cache and slab. This is required
|
|
|
|
* for the slab allocator to be able to lookup the cache and slab of a
|
2011-01-07 06:49:17 +00:00
|
|
|
* virtual address for kfree, ksize, and slab debugging.
|
2006-06-23 09:03:07 +00:00
|
|
|
*/
|
|
|
|
static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
|
|
|
|
void *addr)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-06-23 09:03:07 +00:00
|
|
|
int nr_pages;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct page *page;
|
|
|
|
|
2006-06-23 09:03:07 +00:00
|
|
|
page = virt_to_page(addr);
|
2006-03-22 08:08:34 +00:00
|
|
|
|
2006-06-23 09:03:07 +00:00
|
|
|
nr_pages = 1;
|
2006-03-22 08:08:34 +00:00
|
|
|
if (likely(!PageCompound(page)))
|
2006-06-23 09:03:07 +00:00
|
|
|
nr_pages <<= cache->gfporder;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
do {
|
2012-06-13 15:24:56 +00:00
|
|
|
page->slab_cache = cache;
|
|
|
|
page->slab_page = slab;
|
2005-04-16 22:20:36 +00:00
|
|
|
page++;
|
2006-06-23 09:03:07 +00:00
|
|
|
} while (--nr_pages);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Grow (by 1) the number of slabs within a cache. This is called by
|
|
|
|
* kmem_cache_alloc() when there are no active objs left in a cache.
|
|
|
|
*/
|
2006-12-07 04:33:29 +00:00
|
|
|
static int cache_grow(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags, int nodeid, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
size_t offset;
|
|
|
|
gfp_t local_flags;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Be lazy and only check for valid flags here, keeping it out of the
|
|
|
|
* critical path in kmem_cache_alloc().
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2007-10-16 08:25:41 +00:00
|
|
|
BUG_ON(flags & GFP_SLAB_BUG_MASK);
|
|
|
|
local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-05 07:27:56 +00:00
|
|
|
/* Take the l3 list lock to change the colour_next on this node */
|
2005-04-16 22:20:36 +00:00
|
|
|
check_irq_off();
|
2006-02-05 07:27:56 +00:00
|
|
|
l3 = cachep->nodelists[nodeid];
|
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Get colour for the slab, and cal the next value. */
|
2006-02-05 07:27:56 +00:00
|
|
|
offset = l3->colour_next;
|
|
|
|
l3->colour_next++;
|
|
|
|
if (l3->colour_next >= cachep->colour)
|
|
|
|
l3->colour_next = 0;
|
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-02-05 07:27:56 +00:00
|
|
|
offset *= cachep->colour_off;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_enable();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The test for missing atomic flag is performed here, rather than
|
|
|
|
* the more obvious place, simply to reduce the critical path length
|
|
|
|
* in kmem_cache_alloc(). If a caller is seriously mis-behaving they
|
|
|
|
* will eventually be caught here (where it matters).
|
|
|
|
*/
|
|
|
|
kmem_flagcheck(cachep, flags);
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* Get mem for the objs. Attempt to allocate a physical page from
|
|
|
|
* 'nodeid'.
|
2005-09-09 20:03:32 +00:00
|
|
|
*/
|
2006-12-07 04:33:29 +00:00
|
|
|
if (!objp)
|
2007-07-24 19:02:40 +00:00
|
|
|
objp = kmem_getpages(cachep, local_flags, nodeid);
|
2006-03-22 08:08:11 +00:00
|
|
|
if (!objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
goto failed;
|
|
|
|
|
|
|
|
/* Get slab management. */
|
2006-12-07 04:33:29 +00:00
|
|
|
slabp = alloc_slabmgmt(cachep, objp, offset,
|
2007-10-16 08:25:41 +00:00
|
|
|
local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
|
2006-03-22 08:08:11 +00:00
|
|
|
if (!slabp)
|
2005-04-16 22:20:36 +00:00
|
|
|
goto opps1;
|
|
|
|
|
2006-06-23 09:03:07 +00:00
|
|
|
slab_map_pages(cachep, slabp, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-05-17 05:10:57 +00:00
|
|
|
cache_init_objs(cachep, slabp);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_disable();
|
|
|
|
check_irq_off();
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Make slab active. */
|
2005-09-09 20:03:32 +00:00
|
|
|
list_add_tail(&slabp->list, &(l3->slabs_free));
|
2005-04-16 22:20:36 +00:00
|
|
|
STATS_INC_GROWN(cachep);
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->free_objects += cachep->num;
|
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
return 1;
|
2006-03-22 08:08:11 +00:00
|
|
|
opps1:
|
2005-04-16 22:20:36 +00:00
|
|
|
kmem_freepages(cachep, objp);
|
2006-03-22 08:08:11 +00:00
|
|
|
failed:
|
2005-04-16 22:20:36 +00:00
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_disable();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform extra freeing checks:
|
|
|
|
* - detect bad pointers.
|
|
|
|
* - POISON/RED_ZONE checking
|
|
|
|
*/
|
|
|
|
static void kfree_debugcheck(const void *objp)
|
|
|
|
{
|
|
|
|
if (!virt_addr_valid(objp)) {
|
|
|
|
printk(KERN_ERR "kfree_debugcheck: out of range ptr %lxh.\n",
|
2006-01-08 09:00:37 +00:00
|
|
|
(unsigned long)objp);
|
|
|
|
BUG();
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-23 09:03:24 +00:00
|
|
|
static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
|
|
|
|
{
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
unsigned long long redzone1, redzone2;
|
2006-06-23 09:03:24 +00:00
|
|
|
|
|
|
|
redzone1 = *dbg_redzone1(cache, obj);
|
|
|
|
redzone2 = *dbg_redzone2(cache, obj);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Redzone is ok.
|
|
|
|
*/
|
|
|
|
if (redzone1 == RED_ACTIVE && redzone2 == RED_ACTIVE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (redzone1 == RED_INACTIVE && redzone2 == RED_INACTIVE)
|
|
|
|
slab_error(cache, "double free detected");
|
|
|
|
else
|
|
|
|
slab_error(cache, "memory outside object was overwritten");
|
|
|
|
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
printk(KERN_ERR "%p: redzone 1:0x%llx, redzone 2:0x%llx.\n",
|
2006-06-23 09:03:24 +00:00
|
|
|
obj, redzone1, redzone2);
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
|
2012-09-08 20:47:55 +00:00
|
|
|
unsigned long caller)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct page *page;
|
|
|
|
unsigned int objnr;
|
|
|
|
struct slab *slabp;
|
|
|
|
|
2007-11-29 19:05:13 +00:00
|
|
|
BUG_ON(virt_to_cache(objp) != cachep);
|
|
|
|
|
2006-02-01 11:05:42 +00:00
|
|
|
objp -= obj_offset(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
kfree_debugcheck(objp);
|
2007-05-06 21:49:41 +00:00
|
|
|
page = virt_to_head_page(objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-06-13 15:24:56 +00:00
|
|
|
slabp = page->slab_page;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
2006-06-23 09:03:24 +00:00
|
|
|
verify_redzone_free(cachep, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
|
|
|
|
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
|
|
|
|
}
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
2012-09-08 20:47:55 +00:00
|
|
|
*dbg_userword(cachep, objp) = (void *)caller;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:08:10 +00:00
|
|
|
objnr = obj_to_index(cachep, slabp, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
BUG_ON(objnr >= cachep->num);
|
2006-03-22 08:08:10 +00:00
|
|
|
BUG_ON(objp != index_to_obj(cachep, slabp, objnr));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-25 11:06:39 +00:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
slab_bufctl(slabp)[objnr] = BUFCTL_FREE;
|
|
|
|
#endif
|
2005-04-16 22:20:36 +00:00
|
|
|
if (cachep->flags & SLAB_POISON) {
|
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2012-06-13 15:24:57 +00:00
|
|
|
if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
|
2012-09-08 20:47:55 +00:00
|
|
|
store_stackinfo(cachep, objp, caller);
|
2006-01-08 09:00:37 +00:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->size / PAGE_SIZE, 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
|
|
|
poison_obj(cachep, objp, POISON_FREE);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
poison_obj(cachep, objp, POISON_FREE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void check_slabp(struct kmem_cache *cachep, struct slab *slabp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
kmem_bufctl_t i;
|
|
|
|
int entries = 0;
|
2006-01-08 09:00:37 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Check slab's freelist to see if this obj is there. */
|
|
|
|
for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
|
|
|
|
entries++;
|
|
|
|
if (entries > cachep->num || i >= cachep->num)
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (entries != cachep->num - slabp->inuse) {
|
2006-03-22 08:08:11 +00:00
|
|
|
bad:
|
|
|
|
printk(KERN_ERR "slab: Internal list corruption detected in "
|
2011-11-15 23:03:52 +00:00
|
|
|
"cache '%s'(%d), slabp %p(%d). Tainted(%s). Hexdump:\n",
|
|
|
|
cachep->name, cachep->num, slabp, slabp->inuse,
|
|
|
|
print_tainted());
|
2011-07-29 16:22:13 +00:00
|
|
|
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, slabp,
|
|
|
|
sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t),
|
|
|
|
1);
|
2005-04-16 22:20:36 +00:00
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define kfree_debugcheck(x) do { } while(0)
|
|
|
|
#define cache_free_debugcheck(x,objp,z) (objp)
|
|
|
|
#define check_slabp(x,y) do { } while(0)
|
|
|
|
#endif
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags,
|
|
|
|
bool force_refill)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int batchcount;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
struct array_cache *ac;
|
2006-10-06 07:43:52 +00:00
|
|
|
int node;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
check_irq_off();
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
node = numa_mem_id();
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
if (unlikely(force_refill))
|
|
|
|
goto force_grow;
|
|
|
|
retry:
|
2006-02-01 11:05:49 +00:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
batchcount = ac->batchcount;
|
|
|
|
if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* If there was little recent activity on this cache, then
|
|
|
|
* perform only a partial refill. Otherwise we could generate
|
|
|
|
* refill bouncing.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
batchcount = BATCHREFILL_LIMIT;
|
|
|
|
}
|
2006-10-06 07:43:52 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
2005-09-09 20:03:32 +00:00
|
|
|
|
|
|
|
BUG_ON(ac->avail > 0 || !l3);
|
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-25 11:06:44 +00:00
|
|
|
/* See if we can refill from the shared array */
|
2010-01-27 11:27:40 +00:00
|
|
|
if (l3->shared && transfer_objects(ac, l3->shared, batchcount)) {
|
|
|
|
l3->shared->touched = 1;
|
2006-03-25 11:06:44 +00:00
|
|
|
goto alloc_done;
|
2010-01-27 11:27:40 +00:00
|
|
|
}
|
2006-03-25 11:06:44 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
while (batchcount > 0) {
|
|
|
|
struct list_head *entry;
|
|
|
|
struct slab *slabp;
|
|
|
|
/* Get slab alloc is to come from. */
|
|
|
|
entry = l3->slabs_partial.next;
|
|
|
|
if (entry == &l3->slabs_partial) {
|
|
|
|
l3->free_touched = 1;
|
|
|
|
entry = l3->slabs_free.next;
|
|
|
|
if (entry == &l3->slabs_free)
|
|
|
|
goto must_grow;
|
|
|
|
}
|
|
|
|
|
|
|
|
slabp = list_entry(entry, struct slab, list);
|
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
check_spinlock_acquired(cachep);
|
2007-05-06 21:49:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The slab was either on partial or free list so
|
|
|
|
* there must be at least one object available for
|
|
|
|
* allocation.
|
|
|
|
*/
|
2008-10-29 21:18:07 +00:00
|
|
|
BUG_ON(slabp->inuse >= cachep->num);
|
2007-05-06 21:49:03 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
while (slabp->inuse < cachep->num && batchcount--) {
|
|
|
|
STATS_INC_ALLOCED(cachep);
|
|
|
|
STATS_INC_ACTIVE(cachep);
|
|
|
|
STATS_SET_HIGH(cachep);
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
ac_put_obj(cachep, ac, slab_get_obj(cachep, slabp,
|
|
|
|
node));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
|
|
|
|
/* move slabp to correct slabp list: */
|
|
|
|
list_del(&slabp->list);
|
|
|
|
if (slabp->free == BUFCTL_END)
|
|
|
|
list_add(&slabp->list, &l3->slabs_full);
|
|
|
|
else
|
|
|
|
list_add(&slabp->list, &l3->slabs_partial);
|
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
must_grow:
|
2005-04-16 22:20:36 +00:00
|
|
|
l3->free_objects -= ac->avail;
|
2006-03-22 08:08:11 +00:00
|
|
|
alloc_done:
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (unlikely(!ac->avail)) {
|
|
|
|
int x;
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
force_grow:
|
2006-12-07 04:33:29 +00:00
|
|
|
x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/* cache_grow can reenable interrupts, then ac could change. */
|
2006-02-01 11:05:49 +00:00
|
|
|
ac = cpu_cache_get(cachep);
|
2012-08-29 02:57:21 +00:00
|
|
|
node = numa_mem_id();
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
|
|
|
|
/* no objects in sight? abort */
|
|
|
|
if (!x && (ac->avail == 0 || force_refill))
|
2005-04-16 22:20:36 +00:00
|
|
|
return NULL;
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
if (!ac->avail) /* objects refilled by interrupt? */
|
2005-04-16 22:20:36 +00:00
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
ac->touched = 1;
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
|
|
|
|
return ac_get_obj(cachep, ac, flags, force_refill);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
might_sleep_if(flags & __GFP_WAIT);
|
|
|
|
#if DEBUG
|
|
|
|
kmem_flagcheck(cachep, flags);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
2006-03-22 08:08:11 +00:00
|
|
|
static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
|
2012-09-08 20:47:55 +00:00
|
|
|
gfp_t flags, void *objp, unsigned long caller)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
if (!objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
return objp;
|
2006-01-08 09:00:37 +00:00
|
|
|
if (cachep->flags & SLAB_POISON) {
|
2005-04-16 22:20:36 +00:00
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2012-06-13 15:24:57 +00:00
|
|
|
if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
|
2006-01-08 09:00:37 +00:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2012-06-13 15:24:57 +00:00
|
|
|
cachep->size / PAGE_SIZE, 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
|
|
|
check_poison_obj(cachep, objp);
|
|
|
|
#else
|
|
|
|
check_poison_obj(cachep, objp);
|
|
|
|
#endif
|
|
|
|
poison_obj(cachep, objp, POISON_INUSE);
|
|
|
|
}
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
2012-09-08 20:47:55 +00:00
|
|
|
*dbg_userword(cachep, objp) = (void *)caller;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
2006-03-22 08:08:11 +00:00
|
|
|
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE ||
|
|
|
|
*dbg_redzone2(cachep, objp) != RED_INACTIVE) {
|
|
|
|
slab_error(cachep, "double free, or memory outside"
|
|
|
|
" object was overwritten");
|
2006-01-08 09:00:37 +00:00
|
|
|
printk(KERN_ERR
|
Increase slab redzone to 64bits
There are two problems with the existing redzone implementation.
Firstly, it's causing misalignment of structures which contain a 64-bit
integer, such as netfilter's 'struct ipt_entry' -- causing netfilter
modules to fail to load because of the misalignment. (In particular, the
first check in
net/ipv4/netfilter/ip_tables.c::check_entry_size_and_hooks())
On ppc32 and sparc32, amongst others, __alignof__(uint64_t) == 8.
With slab debugging, we use 32-bit redzones. And allocated slab objects
aren't sufficiently aligned to hold a structure containing a uint64_t.
By _just_ setting ARCH_KMALLOC_MINALIGN to __alignof__(u64) we'd disable
redzone checks on those architectures. By using 64-bit redzones we avoid that
loss of debugging, and also fix the other problem while we're at it.
When investigating this, I noticed that on 64-bit platforms we're using a
32-bit value of RED_ACTIVE/RED_INACTIVE in the 64-bit memory location set
aside for the redzone. Which means that the four bytes immediately before
or after the allocated object at 0x00,0x00,0x00,0x00 for LE and BE
machines, respectively. Which is probably not the most useful choice of
poison value.
One way to fix both of those at once is just to switch to 64-bit
redzones in all cases.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Christoph Lameter <clameter@engr.sgi.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-08 07:22:59 +00:00
|
|
|
"%p: redzone 1:0x%llx, redzone 2:0x%llx\n",
|
2006-03-22 08:08:11 +00:00
|
|
|
objp, *dbg_redzone1(cachep, objp),
|
|
|
|
*dbg_redzone2(cachep, objp));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
*dbg_redzone1(cachep, objp) = RED_ACTIVE;
|
|
|
|
*dbg_redzone2(cachep, objp) = RED_ACTIVE;
|
|
|
|
}
|
2006-03-25 11:06:39 +00:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
{
|
|
|
|
struct slab *slabp;
|
|
|
|
unsigned objnr;
|
|
|
|
|
2012-06-13 15:24:56 +00:00
|
|
|
slabp = virt_to_head_page(objp)->slab_page;
|
2012-06-13 15:24:57 +00:00
|
|
|
objnr = (unsigned)(objp - slabp->s_mem) / cachep->size;
|
2006-03-25 11:06:39 +00:00
|
|
|
slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE;
|
|
|
|
}
|
|
|
|
#endif
|
2006-02-01 11:05:42 +00:00
|
|
|
objp += obj_offset(cachep);
|
2007-05-06 21:50:17 +00:00
|
|
|
if (cachep->ctor && cachep->flags & SLAB_POISON)
|
2008-07-26 02:45:34 +00:00
|
|
|
cachep->ctor(objp);
|
2011-07-21 00:42:45 +00:00
|
|
|
if (ARCH_SLAB_MINALIGN &&
|
|
|
|
((unsigned long)objp & (ARCH_SLAB_MINALIGN-1))) {
|
2006-12-07 04:32:11 +00:00
|
|
|
printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
|
2011-07-11 20:35:08 +00:00
|
|
|
objp, (int)ARCH_SLAB_MINALIGN);
|
2006-12-07 04:32:11 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
|
|
|
|
#endif
|
|
|
|
|
2008-12-23 10:37:01 +00:00
|
|
|
static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
|
2006-12-08 10:39:44 +00:00
|
|
|
{
|
2012-09-05 00:20:33 +00:00
|
|
|
if (cachep == kmem_cache)
|
2008-12-23 10:37:01 +00:00
|
|
|
return false;
|
2006-12-08 10:39:44 +00:00
|
|
|
|
2012-06-13 15:24:58 +00:00
|
|
|
return should_failslab(cachep->object_size, flags, cachep->flags);
|
2006-12-08 10:39:44 +00:00
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
void *objp;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct array_cache *ac;
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
bool force_refill = false;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-09-28 04:45:46 +00:00
|
|
|
check_irq_off();
|
2006-12-08 10:39:44 +00:00
|
|
|
|
2006-02-01 11:05:49 +00:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (likely(ac->avail)) {
|
|
|
|
ac->touched = 1;
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
objp = ac_get_obj(cachep, ac, flags, false);
|
|
|
|
|
2009-12-02 07:55:50 +00:00
|
|
|
/*
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
* Allow for the possibility all avail objects are not allowed
|
|
|
|
* by the current flags
|
2009-12-02 07:55:50 +00:00
|
|
|
*/
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
if (objp) {
|
|
|
|
STATS_INC_ALLOCHIT(cachep);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
force_refill = true;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
|
|
|
|
STATS_INC_ALLOCMISS(cachep);
|
|
|
|
objp = cache_alloc_refill(cachep, flags, force_refill);
|
|
|
|
/*
|
|
|
|
* the 'ac' may be updated by cache_alloc_refill(),
|
|
|
|
* and kmemleak_erase() requires its correct value.
|
|
|
|
*/
|
|
|
|
ac = cpu_cache_get(cachep);
|
|
|
|
|
|
|
|
out:
|
2009-06-11 12:22:40 +00:00
|
|
|
/*
|
|
|
|
* To avoid a false negative, if an object that is in one of the
|
|
|
|
* per-CPU caches is leaked, we need to make sure kmemleak doesn't
|
|
|
|
* treat the array pointers as a reference to the object.
|
|
|
|
*/
|
2009-12-02 07:55:49 +00:00
|
|
|
if (objp)
|
|
|
|
kmemleak_erase(&ac->entry[ac->avail]);
|
2005-09-28 04:45:46 +00:00
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
#ifdef CONFIG_NUMA
|
2006-03-24 11:16:08 +00:00
|
|
|
/*
|
2006-03-24 11:16:12 +00:00
|
|
|
* Try allocating on another node if PF_SPREAD_SLAB|PF_MEMPOLICY.
|
2006-03-24 11:16:08 +00:00
|
|
|
*
|
|
|
|
* If we are in_interrupt, then process context, including cpusets and
|
|
|
|
* mempolicy, may not apply and should not be used for allocation policy.
|
|
|
|
*/
|
|
|
|
static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
|
|
|
|
{
|
|
|
|
int nid_alloc, nid_here;
|
|
|
|
|
2006-09-27 08:50:08 +00:00
|
|
|
if (in_interrupt() || (flags & __GFP_THISNODE))
|
2006-03-24 11:16:08 +00:00
|
|
|
return NULL;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
nid_alloc = nid_here = numa_mem_id();
|
2006-03-24 11:16:08 +00:00
|
|
|
if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
|
2010-05-26 21:42:49 +00:00
|
|
|
nid_alloc = cpuset_slab_spread_node();
|
2006-03-24 11:16:08 +00:00
|
|
|
else if (current->mempolicy)
|
2012-06-09 09:40:03 +00:00
|
|
|
nid_alloc = slab_node();
|
2006-03-24 11:16:08 +00:00
|
|
|
if (nid_alloc != nid_here)
|
2006-12-07 04:32:30 +00:00
|
|
|
return ____cache_alloc_node(cachep, flags, nid_alloc);
|
2006-03-24 11:16:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-09-27 08:50:08 +00:00
|
|
|
/*
|
|
|
|
* Fallback function if there was no memory available and no objects on a
|
2006-12-07 04:33:29 +00:00
|
|
|
* certain node and fall back is permitted. First we scan all the
|
|
|
|
* available nodelists for available objects. If that fails then we
|
|
|
|
* perform an allocation without specifying a node. This allows the page
|
|
|
|
* allocator to do its reclaim / fallback magic. We then insert the
|
|
|
|
* slab into the proper nodelist and then allocate from it.
|
2006-09-27 08:50:08 +00:00
|
|
|
*/
|
2007-02-10 09:42:53 +00:00
|
|
|
static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
|
2006-09-27 08:50:08 +00:00
|
|
|
{
|
2007-02-10 09:42:53 +00:00
|
|
|
struct zonelist *zonelist;
|
|
|
|
gfp_t local_flags;
|
2008-04-28 09:12:17 +00:00
|
|
|
struct zoneref *z;
|
2008-04-28 09:12:16 +00:00
|
|
|
struct zone *zone;
|
|
|
|
enum zone_type high_zoneidx = gfp_zone(flags);
|
2006-09-27 08:50:08 +00:00
|
|
|
void *obj = NULL;
|
2006-12-07 04:33:29 +00:00
|
|
|
int nid;
|
cpuset: mm: reduce large amounts of memory barrier related damage v3
Commit c0ff7453bb5c ("cpuset,mm: fix no node to alloc memory when
changing cpuset's mems") wins a super prize for the largest number of
memory barriers entered into fast paths for one commit.
[get|put]_mems_allowed is incredibly heavy with pairs of full memory
barriers inserted into a number of hot paths. This was detected while
investigating at large page allocator slowdown introduced some time
after 2.6.32. The largest portion of this overhead was shown by
oprofile to be at an mfence introduced by this commit into the page
allocator hot path.
For extra style points, the commit introduced the use of yield() in an
implementation of what looks like a spinning mutex.
This patch replaces the full memory barriers on both read and write
sides with a sequence counter with just read barriers on the fast path
side. This is much cheaper on some architectures, including x86. The
main bulk of the patch is the retry logic if the nodemask changes in a
manner that can cause a false failure.
While updating the nodemask, a check is made to see if a false failure
is a risk. If it is, the sequence number gets bumped and parallel
allocators will briefly stall while the nodemask update takes place.
In a page fault test microbenchmark, oprofile samples from
__alloc_pages_nodemask went from 4.53% of all samples to 1.15%. The
actual results were
3.3.0-rc3 3.3.0-rc3
rc3-vanilla nobarrier-v2r1
Clients 1 UserTime 0.07 ( 0.00%) 0.08 (-14.19%)
Clients 2 UserTime 0.07 ( 0.00%) 0.07 ( 2.72%)
Clients 4 UserTime 0.08 ( 0.00%) 0.07 ( 3.29%)
Clients 1 SysTime 0.70 ( 0.00%) 0.65 ( 6.65%)
Clients 2 SysTime 0.85 ( 0.00%) 0.82 ( 3.65%)
Clients 4 SysTime 1.41 ( 0.00%) 1.41 ( 0.32%)
Clients 1 WallTime 0.77 ( 0.00%) 0.74 ( 4.19%)
Clients 2 WallTime 0.47 ( 0.00%) 0.45 ( 3.73%)
Clients 4 WallTime 0.38 ( 0.00%) 0.37 ( 1.58%)
Clients 1 Flt/sec/cpu 497620.28 ( 0.00%) 520294.53 ( 4.56%)
Clients 2 Flt/sec/cpu 414639.05 ( 0.00%) 429882.01 ( 3.68%)
Clients 4 Flt/sec/cpu 257959.16 ( 0.00%) 258761.48 ( 0.31%)
Clients 1 Flt/sec 495161.39 ( 0.00%) 517292.87 ( 4.47%)
Clients 2 Flt/sec 820325.95 ( 0.00%) 850289.77 ( 3.65%)
Clients 4 Flt/sec 1020068.93 ( 0.00%) 1022674.06 ( 0.26%)
MMTests Statistics: duration
Sys Time Running Test (seconds) 135.68 132.17
User+Sys Time Running Test (seconds) 164.2 160.13
Total Elapsed Time (seconds) 123.46 120.87
The overall improvement is small but the System CPU time is much
improved and roughly in correlation to what oprofile reported (these
performance figures are without profiling so skew is expected). The
actual number of page faults is noticeably improved.
For benchmarks like kernel builds, the overall benefit is marginal but
the system CPU time is slightly reduced.
To test the actual bug the commit fixed I opened two terminals. The
first ran within a cpuset and continually ran a small program that
faulted 100M of anonymous data. In a second window, the nodemask of the
cpuset was continually randomised in a loop.
Without the commit, the program would fail every so often (usually
within 10 seconds) and obviously with the commit everything worked fine.
With this patch applied, it also worked fine so the fix should be
functionally equivalent.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: Miao Xie <miaox@cn.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-03-21 23:34:11 +00:00
|
|
|
unsigned int cpuset_mems_cookie;
|
2007-02-10 09:42:53 +00:00
|
|
|
|
|
|
|
if (flags & __GFP_THISNODE)
|
|
|
|
return NULL;
|
|
|
|
|
2007-10-16 08:25:41 +00:00
|
|
|
local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
|
2006-09-27 08:50:08 +00:00
|
|
|
|
cpuset: mm: reduce large amounts of memory barrier related damage v3
Commit c0ff7453bb5c ("cpuset,mm: fix no node to alloc memory when
changing cpuset's mems") wins a super prize for the largest number of
memory barriers entered into fast paths for one commit.
[get|put]_mems_allowed is incredibly heavy with pairs of full memory
barriers inserted into a number of hot paths. This was detected while
investigating at large page allocator slowdown introduced some time
after 2.6.32. The largest portion of this overhead was shown by
oprofile to be at an mfence introduced by this commit into the page
allocator hot path.
For extra style points, the commit introduced the use of yield() in an
implementation of what looks like a spinning mutex.
This patch replaces the full memory barriers on both read and write
sides with a sequence counter with just read barriers on the fast path
side. This is much cheaper on some architectures, including x86. The
main bulk of the patch is the retry logic if the nodemask changes in a
manner that can cause a false failure.
While updating the nodemask, a check is made to see if a false failure
is a risk. If it is, the sequence number gets bumped and parallel
allocators will briefly stall while the nodemask update takes place.
In a page fault test microbenchmark, oprofile samples from
__alloc_pages_nodemask went from 4.53% of all samples to 1.15%. The
actual results were
3.3.0-rc3 3.3.0-rc3
rc3-vanilla nobarrier-v2r1
Clients 1 UserTime 0.07 ( 0.00%) 0.08 (-14.19%)
Clients 2 UserTime 0.07 ( 0.00%) 0.07 ( 2.72%)
Clients 4 UserTime 0.08 ( 0.00%) 0.07 ( 3.29%)
Clients 1 SysTime 0.70 ( 0.00%) 0.65 ( 6.65%)
Clients 2 SysTime 0.85 ( 0.00%) 0.82 ( 3.65%)
Clients 4 SysTime 1.41 ( 0.00%) 1.41 ( 0.32%)
Clients 1 WallTime 0.77 ( 0.00%) 0.74 ( 4.19%)
Clients 2 WallTime 0.47 ( 0.00%) 0.45 ( 3.73%)
Clients 4 WallTime 0.38 ( 0.00%) 0.37 ( 1.58%)
Clients 1 Flt/sec/cpu 497620.28 ( 0.00%) 520294.53 ( 4.56%)
Clients 2 Flt/sec/cpu 414639.05 ( 0.00%) 429882.01 ( 3.68%)
Clients 4 Flt/sec/cpu 257959.16 ( 0.00%) 258761.48 ( 0.31%)
Clients 1 Flt/sec 495161.39 ( 0.00%) 517292.87 ( 4.47%)
Clients 2 Flt/sec 820325.95 ( 0.00%) 850289.77 ( 3.65%)
Clients 4 Flt/sec 1020068.93 ( 0.00%) 1022674.06 ( 0.26%)
MMTests Statistics: duration
Sys Time Running Test (seconds) 135.68 132.17
User+Sys Time Running Test (seconds) 164.2 160.13
Total Elapsed Time (seconds) 123.46 120.87
The overall improvement is small but the System CPU time is much
improved and roughly in correlation to what oprofile reported (these
performance figures are without profiling so skew is expected). The
actual number of page faults is noticeably improved.
For benchmarks like kernel builds, the overall benefit is marginal but
the system CPU time is slightly reduced.
To test the actual bug the commit fixed I opened two terminals. The
first ran within a cpuset and continually ran a small program that
faulted 100M of anonymous data. In a second window, the nodemask of the
cpuset was continually randomised in a loop.
Without the commit, the program would fail every so often (usually
within 10 seconds) and obviously with the commit everything worked fine.
With this patch applied, it also worked fine so the fix should be
functionally equivalent.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: Miao Xie <miaox@cn.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-03-21 23:34:11 +00:00
|
|
|
retry_cpuset:
|
|
|
|
cpuset_mems_cookie = get_mems_allowed();
|
2012-06-09 09:40:03 +00:00
|
|
|
zonelist = node_zonelist(slab_node(), flags);
|
cpuset: mm: reduce large amounts of memory barrier related damage v3
Commit c0ff7453bb5c ("cpuset,mm: fix no node to alloc memory when
changing cpuset's mems") wins a super prize for the largest number of
memory barriers entered into fast paths for one commit.
[get|put]_mems_allowed is incredibly heavy with pairs of full memory
barriers inserted into a number of hot paths. This was detected while
investigating at large page allocator slowdown introduced some time
after 2.6.32. The largest portion of this overhead was shown by
oprofile to be at an mfence introduced by this commit into the page
allocator hot path.
For extra style points, the commit introduced the use of yield() in an
implementation of what looks like a spinning mutex.
This patch replaces the full memory barriers on both read and write
sides with a sequence counter with just read barriers on the fast path
side. This is much cheaper on some architectures, including x86. The
main bulk of the patch is the retry logic if the nodemask changes in a
manner that can cause a false failure.
While updating the nodemask, a check is made to see if a false failure
is a risk. If it is, the sequence number gets bumped and parallel
allocators will briefly stall while the nodemask update takes place.
In a page fault test microbenchmark, oprofile samples from
__alloc_pages_nodemask went from 4.53% of all samples to 1.15%. The
actual results were
3.3.0-rc3 3.3.0-rc3
rc3-vanilla nobarrier-v2r1
Clients 1 UserTime 0.07 ( 0.00%) 0.08 (-14.19%)
Clients 2 UserTime 0.07 ( 0.00%) 0.07 ( 2.72%)
Clients 4 UserTime 0.08 ( 0.00%) 0.07 ( 3.29%)
Clients 1 SysTime 0.70 ( 0.00%) 0.65 ( 6.65%)
Clients 2 SysTime 0.85 ( 0.00%) 0.82 ( 3.65%)
Clients 4 SysTime 1.41 ( 0.00%) 1.41 ( 0.32%)
Clients 1 WallTime 0.77 ( 0.00%) 0.74 ( 4.19%)
Clients 2 WallTime 0.47 ( 0.00%) 0.45 ( 3.73%)
Clients 4 WallTime 0.38 ( 0.00%) 0.37 ( 1.58%)
Clients 1 Flt/sec/cpu 497620.28 ( 0.00%) 520294.53 ( 4.56%)
Clients 2 Flt/sec/cpu 414639.05 ( 0.00%) 429882.01 ( 3.68%)
Clients 4 Flt/sec/cpu 257959.16 ( 0.00%) 258761.48 ( 0.31%)
Clients 1 Flt/sec 495161.39 ( 0.00%) 517292.87 ( 4.47%)
Clients 2 Flt/sec 820325.95 ( 0.00%) 850289.77 ( 3.65%)
Clients 4 Flt/sec 1020068.93 ( 0.00%) 1022674.06 ( 0.26%)
MMTests Statistics: duration
Sys Time Running Test (seconds) 135.68 132.17
User+Sys Time Running Test (seconds) 164.2 160.13
Total Elapsed Time (seconds) 123.46 120.87
The overall improvement is small but the System CPU time is much
improved and roughly in correlation to what oprofile reported (these
performance figures are without profiling so skew is expected). The
actual number of page faults is noticeably improved.
For benchmarks like kernel builds, the overall benefit is marginal but
the system CPU time is slightly reduced.
To test the actual bug the commit fixed I opened two terminals. The
first ran within a cpuset and continually ran a small program that
faulted 100M of anonymous data. In a second window, the nodemask of the
cpuset was continually randomised in a loop.
Without the commit, the program would fail every so often (usually
within 10 seconds) and obviously with the commit everything worked fine.
With this patch applied, it also worked fine so the fix should be
functionally equivalent.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: Miao Xie <miaox@cn.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-03-21 23:34:11 +00:00
|
|
|
|
2006-12-07 04:33:29 +00:00
|
|
|
retry:
|
|
|
|
/*
|
|
|
|
* Look through allowed nodes for objects available
|
|
|
|
* from existing per node queues.
|
|
|
|
*/
|
2008-04-28 09:12:16 +00:00
|
|
|
for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
|
|
|
|
nid = zone_to_nid(zone);
|
2006-10-21 17:24:16 +00:00
|
|
|
|
2008-04-28 09:12:16 +00:00
|
|
|
if (cpuset_zone_allowed_hardwall(zone, flags) &&
|
2006-12-07 04:33:29 +00:00
|
|
|
cache->nodelists[nid] &&
|
2008-06-21 23:46:35 +00:00
|
|
|
cache->nodelists[nid]->free_objects) {
|
2006-12-07 04:33:29 +00:00
|
|
|
obj = ____cache_alloc_node(cache,
|
|
|
|
flags | GFP_THISNODE, nid);
|
2008-06-21 23:46:35 +00:00
|
|
|
if (obj)
|
|
|
|
break;
|
|
|
|
}
|
2006-12-07 04:33:29 +00:00
|
|
|
}
|
|
|
|
|
2007-05-06 21:50:17 +00:00
|
|
|
if (!obj) {
|
2006-12-07 04:33:29 +00:00
|
|
|
/*
|
|
|
|
* This allocation will be performed within the constraints
|
|
|
|
* of the current cpuset / memory policy requirements.
|
|
|
|
* We may trigger various forms of reclaim on the allowed
|
|
|
|
* set and go into memory reserves if necessary.
|
|
|
|
*/
|
2006-12-13 08:34:11 +00:00
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_enable();
|
|
|
|
kmem_flagcheck(cache, flags);
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
obj = kmem_getpages(cache, local_flags, numa_mem_id());
|
2006-12-13 08:34:11 +00:00
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_disable();
|
2006-12-07 04:33:29 +00:00
|
|
|
if (obj) {
|
|
|
|
/*
|
|
|
|
* Insert into the appropriate per node queues
|
|
|
|
*/
|
|
|
|
nid = page_to_nid(virt_to_page(obj));
|
|
|
|
if (cache_grow(cache, flags, nid, obj)) {
|
|
|
|
obj = ____cache_alloc_node(cache,
|
|
|
|
flags | GFP_THISNODE, nid);
|
|
|
|
if (!obj)
|
|
|
|
/*
|
|
|
|
* Another processor may allocate the
|
|
|
|
* objects in the slab since we are
|
|
|
|
* not holding any locks.
|
|
|
|
*/
|
|
|
|
goto retry;
|
|
|
|
} else {
|
2007-01-06 00:36:36 +00:00
|
|
|
/* cache_grow already freed obj */
|
2006-12-07 04:33:29 +00:00
|
|
|
obj = NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-10-21 17:24:16 +00:00
|
|
|
}
|
cpuset: mm: reduce large amounts of memory barrier related damage v3
Commit c0ff7453bb5c ("cpuset,mm: fix no node to alloc memory when
changing cpuset's mems") wins a super prize for the largest number of
memory barriers entered into fast paths for one commit.
[get|put]_mems_allowed is incredibly heavy with pairs of full memory
barriers inserted into a number of hot paths. This was detected while
investigating at large page allocator slowdown introduced some time
after 2.6.32. The largest portion of this overhead was shown by
oprofile to be at an mfence introduced by this commit into the page
allocator hot path.
For extra style points, the commit introduced the use of yield() in an
implementation of what looks like a spinning mutex.
This patch replaces the full memory barriers on both read and write
sides with a sequence counter with just read barriers on the fast path
side. This is much cheaper on some architectures, including x86. The
main bulk of the patch is the retry logic if the nodemask changes in a
manner that can cause a false failure.
While updating the nodemask, a check is made to see if a false failure
is a risk. If it is, the sequence number gets bumped and parallel
allocators will briefly stall while the nodemask update takes place.
In a page fault test microbenchmark, oprofile samples from
__alloc_pages_nodemask went from 4.53% of all samples to 1.15%. The
actual results were
3.3.0-rc3 3.3.0-rc3
rc3-vanilla nobarrier-v2r1
Clients 1 UserTime 0.07 ( 0.00%) 0.08 (-14.19%)
Clients 2 UserTime 0.07 ( 0.00%) 0.07 ( 2.72%)
Clients 4 UserTime 0.08 ( 0.00%) 0.07 ( 3.29%)
Clients 1 SysTime 0.70 ( 0.00%) 0.65 ( 6.65%)
Clients 2 SysTime 0.85 ( 0.00%) 0.82 ( 3.65%)
Clients 4 SysTime 1.41 ( 0.00%) 1.41 ( 0.32%)
Clients 1 WallTime 0.77 ( 0.00%) 0.74 ( 4.19%)
Clients 2 WallTime 0.47 ( 0.00%) 0.45 ( 3.73%)
Clients 4 WallTime 0.38 ( 0.00%) 0.37 ( 1.58%)
Clients 1 Flt/sec/cpu 497620.28 ( 0.00%) 520294.53 ( 4.56%)
Clients 2 Flt/sec/cpu 414639.05 ( 0.00%) 429882.01 ( 3.68%)
Clients 4 Flt/sec/cpu 257959.16 ( 0.00%) 258761.48 ( 0.31%)
Clients 1 Flt/sec 495161.39 ( 0.00%) 517292.87 ( 4.47%)
Clients 2 Flt/sec 820325.95 ( 0.00%) 850289.77 ( 3.65%)
Clients 4 Flt/sec 1020068.93 ( 0.00%) 1022674.06 ( 0.26%)
MMTests Statistics: duration
Sys Time Running Test (seconds) 135.68 132.17
User+Sys Time Running Test (seconds) 164.2 160.13
Total Elapsed Time (seconds) 123.46 120.87
The overall improvement is small but the System CPU time is much
improved and roughly in correlation to what oprofile reported (these
performance figures are without profiling so skew is expected). The
actual number of page faults is noticeably improved.
For benchmarks like kernel builds, the overall benefit is marginal but
the system CPU time is slightly reduced.
To test the actual bug the commit fixed I opened two terminals. The
first ran within a cpuset and continually ran a small program that
faulted 100M of anonymous data. In a second window, the nodemask of the
cpuset was continually randomised in a loop.
Without the commit, the program would fail every so often (usually
within 10 seconds) and obviously with the commit everything worked fine.
With this patch applied, it also worked fine so the fix should be
functionally equivalent.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: Miao Xie <miaox@cn.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-03-21 23:34:11 +00:00
|
|
|
|
|
|
|
if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !obj))
|
|
|
|
goto retry_cpuset;
|
2006-09-27 08:50:08 +00:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
|
|
|
* A interface to enable slab creation on nodeid
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2006-12-07 04:32:30 +00:00
|
|
|
static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
|
2006-03-22 08:08:11 +00:00
|
|
|
int nodeid)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
struct list_head *entry;
|
2006-01-08 09:00:37 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
void *obj;
|
|
|
|
int x;
|
|
|
|
|
|
|
|
l3 = cachep->nodelists[nodeid];
|
|
|
|
BUG_ON(!l3);
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
retry:
|
2006-02-05 07:27:58 +00:00
|
|
|
check_irq_off();
|
2006-01-08 09:00:37 +00:00
|
|
|
spin_lock(&l3->list_lock);
|
|
|
|
entry = l3->slabs_partial.next;
|
|
|
|
if (entry == &l3->slabs_partial) {
|
|
|
|
l3->free_touched = 1;
|
|
|
|
entry = l3->slabs_free.next;
|
|
|
|
if (entry == &l3->slabs_free)
|
|
|
|
goto must_grow;
|
|
|
|
}
|
|
|
|
|
|
|
|
slabp = list_entry(entry, struct slab, list);
|
|
|
|
check_spinlock_acquired_node(cachep, nodeid);
|
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
|
|
|
|
STATS_INC_NODEALLOCS(cachep);
|
|
|
|
STATS_INC_ACTIVE(cachep);
|
|
|
|
STATS_SET_HIGH(cachep);
|
|
|
|
|
|
|
|
BUG_ON(slabp->inuse == cachep->num);
|
|
|
|
|
2006-02-01 11:05:47 +00:00
|
|
|
obj = slab_get_obj(cachep, slabp, nodeid);
|
2006-01-08 09:00:37 +00:00
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
l3->free_objects--;
|
|
|
|
/* move slabp to correct slabp list: */
|
|
|
|
list_del(&slabp->list);
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
if (slabp->free == BUFCTL_END)
|
2006-01-08 09:00:37 +00:00
|
|
|
list_add(&slabp->list, &l3->slabs_full);
|
2006-03-22 08:08:11 +00:00
|
|
|
else
|
2006-01-08 09:00:37 +00:00
|
|
|
list_add(&slabp->list, &l3->slabs_partial);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
spin_unlock(&l3->list_lock);
|
|
|
|
goto done;
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
must_grow:
|
2006-01-08 09:00:37 +00:00
|
|
|
spin_unlock(&l3->list_lock);
|
2006-12-07 04:33:29 +00:00
|
|
|
x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
|
2006-09-27 08:50:08 +00:00
|
|
|
if (x)
|
|
|
|
goto retry;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-02-10 09:42:53 +00:00
|
|
|
return fallback_alloc(cachep, flags);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
done:
|
2006-01-08 09:00:37 +00:00
|
|
|
return obj;
|
2005-09-09 20:03:32 +00:00
|
|
|
}
|
2007-02-10 09:42:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* kmem_cache_alloc_node - Allocate an object on the specified node
|
|
|
|
* @cachep: The cache to allocate from.
|
|
|
|
* @flags: See kmalloc().
|
|
|
|
* @nodeid: node number of the target node.
|
|
|
|
* @caller: return address of caller, used for debug information
|
|
|
|
*
|
|
|
|
* Identical to kmem_cache_alloc but it will allocate memory on the given
|
|
|
|
* node, which can improve the performance for cpu bound structures.
|
|
|
|
*
|
|
|
|
* Fallback to other node is possible if __GFP_THISNODE is not set.
|
|
|
|
*/
|
|
|
|
static __always_inline void *
|
2012-09-08 20:47:57 +00:00
|
|
|
slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
|
2012-09-08 20:47:55 +00:00
|
|
|
unsigned long caller)
|
2007-02-10 09:42:53 +00:00
|
|
|
{
|
|
|
|
unsigned long save_flags;
|
|
|
|
void *ptr;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int slab_node = numa_mem_id();
|
2007-02-10 09:42:53 +00:00
|
|
|
|
2009-06-18 03:24:12 +00:00
|
|
|
flags &= gfp_allowed_mask;
|
2009-06-12 11:03:06 +00:00
|
|
|
|
lockdep: annotate reclaim context (__GFP_NOFS)
Here is another version, with the incremental patch rolled up, and
added reclaim context annotation to kswapd, and allocation tracing
to slab allocators (which may only ever reach the page allocator
in rare cases, so it is good to put annotations here too).
Haven't tested this version as such, but it should be getting closer
to merge worthy ;)
--
After noticing some code in mm/filemap.c accidentally perform a __GFP_FS
allocation when it should not have been, I thought it might be a good idea to
try to catch this kind of thing with lockdep.
I coded up a little idea that seems to work. Unfortunately the system has to
actually be in __GFP_FS page reclaim, then take the lock, before it will mark
it. But at least that might still be some orders of magnitude more common
(and more debuggable) than an actual deadlock condition, so we have some
improvement I hope (the concept is no less complete than discovery of a lock's
interrupt contexts).
I guess we could even do the same thing with __GFP_IO (normal reclaim), and
even GFP_NOIO locks too... but filesystems will have the most locks and fiddly
code paths, so let's start there and see how it goes.
It *seems* to work. I did a quick test.
=================================
[ INFO: inconsistent lock state ]
2.6.28-rc6-00007-ged31348-dirty #26
---------------------------------
inconsistent {in-reclaim-W} -> {ov-reclaim-W} usage.
modprobe/8526 [HC0[0]:SC0[0]:HE1:SE1] takes:
(testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd]
{in-reclaim-W} state was registered at:
[<ffffffff80267bdb>] __lock_acquire+0x75b/0x1a60
[<ffffffff80268f71>] lock_acquire+0x91/0xc0
[<ffffffff8070f0e1>] mutex_lock_nested+0xb1/0x310
[<ffffffffa002002b>] brd_init+0x2b/0x216 [brd]
[<ffffffff8020903b>] _stext+0x3b/0x170
[<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0
[<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
irq event stamp: 3929
hardirqs last enabled at (3929): [<ffffffff8070f2b5>] mutex_lock_nested+0x285/0x310
hardirqs last disabled at (3928): [<ffffffff8070f089>] mutex_lock_nested+0x59/0x310
softirqs last enabled at (3732): [<ffffffff8061f623>] sk_filter+0x83/0xe0
softirqs last disabled at (3730): [<ffffffff8061f5b6>] sk_filter+0x16/0xe0
other info that might help us debug this:
1 lock held by modprobe/8526:
#0: (testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd]
stack backtrace:
Pid: 8526, comm: modprobe Not tainted 2.6.28-rc6-00007-ged31348-dirty #26
Call Trace:
[<ffffffff80265483>] print_usage_bug+0x193/0x1d0
[<ffffffff80266530>] mark_lock+0xaf0/0xca0
[<ffffffff80266735>] mark_held_locks+0x55/0xc0
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffff802667ca>] trace_reclaim_fs+0x2a/0x60
[<ffffffff80285005>] __alloc_pages_internal+0x475/0x580
[<ffffffff8070f29e>] ? mutex_lock_nested+0x26e/0x310
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffffa002006a>] brd_init+0x6a/0x216 [brd]
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffff8020903b>] _stext+0x3b/0x170
[<ffffffff8070f8b9>] ? mutex_unlock+0x9/0x10
[<ffffffff8070f83d>] ? __mutex_unlock_slowpath+0x10d/0x180
[<ffffffff802669ec>] ? trace_hardirqs_on_caller+0x12c/0x190
[<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0
[<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-01-21 07:12:39 +00:00
|
|
|
lockdep_trace_alloc(flags);
|
|
|
|
|
2008-12-23 10:37:01 +00:00
|
|
|
if (slab_should_failslab(cachep, flags))
|
2007-05-06 21:49:58 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-12-18 22:22:48 +00:00
|
|
|
cachep = memcg_kmem_get_cache(cachep, flags);
|
|
|
|
|
2007-02-10 09:42:53 +00:00
|
|
|
cache_alloc_debugcheck_before(cachep, flags);
|
|
|
|
local_irq_save(save_flags);
|
|
|
|
|
2011-07-28 20:59:49 +00:00
|
|
|
if (nodeid == NUMA_NO_NODE)
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
nodeid = slab_node;
|
2007-02-10 09:42:53 +00:00
|
|
|
|
|
|
|
if (unlikely(!cachep->nodelists[nodeid])) {
|
|
|
|
/* Node not bootstrapped yet */
|
|
|
|
ptr = fallback_alloc(cachep, flags);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
if (nodeid == slab_node) {
|
2007-02-10 09:42:53 +00:00
|
|
|
/*
|
|
|
|
* Use the locally cached objects if possible.
|
|
|
|
* However ____cache_alloc does not allow fallback
|
|
|
|
* to other nodes. It may fail while we still have
|
|
|
|
* objects on other nodes available.
|
|
|
|
*/
|
|
|
|
ptr = ____cache_alloc(cachep, flags);
|
|
|
|
if (ptr)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* ___cache_alloc_node can fall back to other nodes */
|
|
|
|
ptr = ____cache_alloc_node(cachep, flags, nodeid);
|
|
|
|
out:
|
|
|
|
local_irq_restore(save_flags);
|
|
|
|
ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
|
2012-06-13 15:24:58 +00:00
|
|
|
kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags,
|
2009-06-11 12:22:40 +00:00
|
|
|
flags);
|
2007-02-10 09:42:53 +00:00
|
|
|
|
2008-05-09 18:35:53 +00:00
|
|
|
if (likely(ptr))
|
2012-06-13 15:24:58 +00:00
|
|
|
kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size);
|
2008-05-09 18:35:53 +00:00
|
|
|
|
2007-07-17 11:03:23 +00:00
|
|
|
if (unlikely((flags & __GFP_ZERO) && ptr))
|
2012-06-13 15:24:58 +00:00
|
|
|
memset(ptr, 0, cachep->object_size);
|
2007-07-17 11:03:23 +00:00
|
|
|
|
2007-02-10 09:42:53 +00:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline void *
|
|
|
|
__do_cache_alloc(struct kmem_cache *cache, gfp_t flags)
|
|
|
|
{
|
|
|
|
void *objp;
|
|
|
|
|
|
|
|
if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY))) {
|
|
|
|
objp = alternate_node_alloc(cache, flags);
|
|
|
|
if (objp)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
objp = ____cache_alloc(cache, flags);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We may just have run out of memory on the local node.
|
|
|
|
* ____cache_alloc_node() knows how to locate memory on other nodes
|
|
|
|
*/
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
if (!objp)
|
|
|
|
objp = ____cache_alloc_node(cache, flags, numa_mem_id());
|
2007-02-10 09:42:53 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
|
|
static __always_inline void *
|
|
|
|
__do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
|
|
|
|
{
|
|
|
|
return ____cache_alloc(cachep, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_NUMA */
|
|
|
|
|
|
|
|
static __always_inline void *
|
2012-09-08 20:47:57 +00:00
|
|
|
slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller)
|
2007-02-10 09:42:53 +00:00
|
|
|
{
|
|
|
|
unsigned long save_flags;
|
|
|
|
void *objp;
|
|
|
|
|
2009-06-18 03:24:12 +00:00
|
|
|
flags &= gfp_allowed_mask;
|
2009-06-12 11:03:06 +00:00
|
|
|
|
lockdep: annotate reclaim context (__GFP_NOFS)
Here is another version, with the incremental patch rolled up, and
added reclaim context annotation to kswapd, and allocation tracing
to slab allocators (which may only ever reach the page allocator
in rare cases, so it is good to put annotations here too).
Haven't tested this version as such, but it should be getting closer
to merge worthy ;)
--
After noticing some code in mm/filemap.c accidentally perform a __GFP_FS
allocation when it should not have been, I thought it might be a good idea to
try to catch this kind of thing with lockdep.
I coded up a little idea that seems to work. Unfortunately the system has to
actually be in __GFP_FS page reclaim, then take the lock, before it will mark
it. But at least that might still be some orders of magnitude more common
(and more debuggable) than an actual deadlock condition, so we have some
improvement I hope (the concept is no less complete than discovery of a lock's
interrupt contexts).
I guess we could even do the same thing with __GFP_IO (normal reclaim), and
even GFP_NOIO locks too... but filesystems will have the most locks and fiddly
code paths, so let's start there and see how it goes.
It *seems* to work. I did a quick test.
=================================
[ INFO: inconsistent lock state ]
2.6.28-rc6-00007-ged31348-dirty #26
---------------------------------
inconsistent {in-reclaim-W} -> {ov-reclaim-W} usage.
modprobe/8526 [HC0[0]:SC0[0]:HE1:SE1] takes:
(testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd]
{in-reclaim-W} state was registered at:
[<ffffffff80267bdb>] __lock_acquire+0x75b/0x1a60
[<ffffffff80268f71>] lock_acquire+0x91/0xc0
[<ffffffff8070f0e1>] mutex_lock_nested+0xb1/0x310
[<ffffffffa002002b>] brd_init+0x2b/0x216 [brd]
[<ffffffff8020903b>] _stext+0x3b/0x170
[<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0
[<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff
irq event stamp: 3929
hardirqs last enabled at (3929): [<ffffffff8070f2b5>] mutex_lock_nested+0x285/0x310
hardirqs last disabled at (3928): [<ffffffff8070f089>] mutex_lock_nested+0x59/0x310
softirqs last enabled at (3732): [<ffffffff8061f623>] sk_filter+0x83/0xe0
softirqs last disabled at (3730): [<ffffffff8061f5b6>] sk_filter+0x16/0xe0
other info that might help us debug this:
1 lock held by modprobe/8526:
#0: (testlock){--..}, at: [<ffffffffa0020055>] brd_init+0x55/0x216 [brd]
stack backtrace:
Pid: 8526, comm: modprobe Not tainted 2.6.28-rc6-00007-ged31348-dirty #26
Call Trace:
[<ffffffff80265483>] print_usage_bug+0x193/0x1d0
[<ffffffff80266530>] mark_lock+0xaf0/0xca0
[<ffffffff80266735>] mark_held_locks+0x55/0xc0
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffff802667ca>] trace_reclaim_fs+0x2a/0x60
[<ffffffff80285005>] __alloc_pages_internal+0x475/0x580
[<ffffffff8070f29e>] ? mutex_lock_nested+0x26e/0x310
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffffa002006a>] brd_init+0x6a/0x216 [brd]
[<ffffffffa0020000>] ? brd_init+0x0/0x216 [brd]
[<ffffffff8020903b>] _stext+0x3b/0x170
[<ffffffff8070f8b9>] ? mutex_unlock+0x9/0x10
[<ffffffff8070f83d>] ? __mutex_unlock_slowpath+0x10d/0x180
[<ffffffff802669ec>] ? trace_hardirqs_on_caller+0x12c/0x190
[<ffffffff80272ebf>] sys_init_module+0xaf/0x1e0
[<ffffffff8020c3fb>] system_call_fastpath+0x16/0x1b
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-01-21 07:12:39 +00:00
|
|
|
lockdep_trace_alloc(flags);
|
|
|
|
|
2008-12-23 10:37:01 +00:00
|
|
|
if (slab_should_failslab(cachep, flags))
|
2007-05-06 21:49:58 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-12-18 22:22:48 +00:00
|
|
|
cachep = memcg_kmem_get_cache(cachep, flags);
|
|
|
|
|
2007-02-10 09:42:53 +00:00
|
|
|
cache_alloc_debugcheck_before(cachep, flags);
|
|
|
|
local_irq_save(save_flags);
|
|
|
|
objp = __do_cache_alloc(cachep, flags);
|
|
|
|
local_irq_restore(save_flags);
|
|
|
|
objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
|
2012-06-13 15:24:58 +00:00
|
|
|
kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags,
|
2009-06-11 12:22:40 +00:00
|
|
|
flags);
|
2007-02-10 09:42:53 +00:00
|
|
|
prefetchw(objp);
|
|
|
|
|
2008-05-09 18:35:53 +00:00
|
|
|
if (likely(objp))
|
2012-06-13 15:24:58 +00:00
|
|
|
kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size);
|
2008-05-09 18:35:53 +00:00
|
|
|
|
2007-07-17 11:03:23 +00:00
|
|
|
if (unlikely((flags & __GFP_ZERO) && objp))
|
2012-06-13 15:24:58 +00:00
|
|
|
memset(objp, 0, cachep->object_size);
|
2007-07-17 11:03:23 +00:00
|
|
|
|
2007-02-10 09:42:53 +00:00
|
|
|
return objp;
|
|
|
|
}
|
2005-09-09 20:03:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Caller needs to acquire correct kmem_list's list_lock
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
|
2006-01-08 09:00:37 +00:00
|
|
|
int node)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int i;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nr_objects; i++) {
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
void *objp;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
clear_obj_pfmemalloc(&objpp[i]);
|
|
|
|
objp = objpp[i];
|
|
|
|
|
2006-02-01 11:05:49 +00:00
|
|
|
slabp = virt_to_slab(objp);
|
2005-09-23 04:44:02 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
2005-04-16 22:20:36 +00:00
|
|
|
list_del(&slabp->list);
|
2005-09-23 04:44:02 +00:00
|
|
|
check_spinlock_acquired_node(cachep, node);
|
2005-04-16 22:20:36 +00:00
|
|
|
check_slabp(cachep, slabp);
|
2006-02-01 11:05:47 +00:00
|
|
|
slab_put_obj(cachep, slabp, objp, node);
|
2005-04-16 22:20:36 +00:00
|
|
|
STATS_DEC_ACTIVE(cachep);
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->free_objects++;
|
2005-04-16 22:20:36 +00:00
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
|
|
|
|
/* fixup slab chains */
|
|
|
|
if (slabp->inuse == 0) {
|
2005-09-09 20:03:32 +00:00
|
|
|
if (l3->free_objects > l3->free_limit) {
|
|
|
|
l3->free_objects -= cachep->num;
|
2006-09-26 06:31:34 +00:00
|
|
|
/* No need to drop any previously held
|
|
|
|
* lock here, even if we have a off-slab slab
|
|
|
|
* descriptor it is guaranteed to come from
|
|
|
|
* a different cache, refer to comments before
|
|
|
|
* alloc_slabmgmt.
|
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
slab_destroy(cachep, slabp);
|
|
|
|
} else {
|
2005-09-09 20:03:32 +00:00
|
|
|
list_add(&slabp->list, &l3->slabs_free);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Unconditionally move a slab to the end of the
|
|
|
|
* partial list on free - maximum time for the
|
|
|
|
* other objects to be freed, too.
|
|
|
|
*/
|
2005-09-09 20:03:32 +00:00
|
|
|
list_add_tail(&slabp->list, &l3->slabs_partial);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-01 11:05:50 +00:00
|
|
|
static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int batchcount;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int node = numa_mem_id();
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
batchcount = ac->batchcount;
|
|
|
|
#if DEBUG
|
|
|
|
BUG_ON(!batchcount || batchcount > ac->avail);
|
|
|
|
#endif
|
|
|
|
check_irq_off();
|
2005-09-23 04:44:02 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-07-13 12:44:38 +00:00
|
|
|
spin_lock(&l3->list_lock);
|
2005-09-09 20:03:32 +00:00
|
|
|
if (l3->shared) {
|
|
|
|
struct array_cache *shared_array = l3->shared;
|
2006-01-08 09:00:37 +00:00
|
|
|
int max = shared_array->limit - shared_array->avail;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (max) {
|
|
|
|
if (batchcount > max)
|
|
|
|
batchcount = max;
|
2005-09-09 20:03:32 +00:00
|
|
|
memcpy(&(shared_array->entry[shared_array->avail]),
|
2006-01-08 09:00:37 +00:00
|
|
|
ac->entry, sizeof(void *) * batchcount);
|
2005-04-16 22:20:36 +00:00
|
|
|
shared_array->avail += batchcount;
|
|
|
|
goto free_done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-23 04:44:02 +00:00
|
|
|
free_block(cachep, ac->entry, batchcount, node);
|
2006-03-22 08:08:11 +00:00
|
|
|
free_done:
|
2005-04-16 22:20:36 +00:00
|
|
|
#if STATS
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
struct list_head *p;
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
p = l3->slabs_free.next;
|
|
|
|
while (p != &(l3->slabs_free)) {
|
2005-04-16 22:20:36 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
|
|
|
|
slabp = list_entry(p, struct slab, list);
|
|
|
|
BUG_ON(slabp->inuse);
|
|
|
|
|
|
|
|
i++;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
STATS_SET_FREEABLE(cachep, i);
|
|
|
|
}
|
|
|
|
#endif
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
ac->avail -= batchcount;
|
2006-03-22 08:08:11 +00:00
|
|
|
memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-03-22 08:08:11 +00:00
|
|
|
* Release an obj back to its cache. If the obj has a constructed state, it must
|
|
|
|
* be in this state _before_ it is released. Called with disabled ints.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2011-06-02 07:16:42 +00:00
|
|
|
static inline void __cache_free(struct kmem_cache *cachep, void *objp,
|
2012-09-08 20:47:55 +00:00
|
|
|
unsigned long caller)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-02-01 11:05:49 +00:00
|
|
|
struct array_cache *ac = cpu_cache_get(cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
check_irq_off();
|
2009-06-11 12:22:40 +00:00
|
|
|
kmemleak_free_recursive(objp, cachep->flags);
|
2011-06-02 07:16:42 +00:00
|
|
|
objp = cache_free_debugcheck(cachep, objp, caller);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-06-13 15:24:58 +00:00
|
|
|
kmemcheck_slab_free(cachep, objp, cachep->object_size);
|
2008-05-09 18:35:53 +00:00
|
|
|
|
2007-08-22 21:01:49 +00:00
|
|
|
/*
|
|
|
|
* Skip calling cache_free_alien() when the platform is not numa.
|
|
|
|
* This will avoid cache misses that happen while accessing slabp (which
|
|
|
|
* is per page memory reference) to get nodeid. Instead use a global
|
|
|
|
* variable to skip the call, which is mostly likely to be present in
|
|
|
|
* the cache.
|
|
|
|
*/
|
2009-06-16 22:32:16 +00:00
|
|
|
if (nr_online_nodes > 1 && cache_free_alien(cachep, objp))
|
2006-06-23 09:03:05 +00:00
|
|
|
return;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (likely(ac->avail < ac->limit)) {
|
|
|
|
STATS_INC_FREEHIT(cachep);
|
|
|
|
} else {
|
|
|
|
STATS_INC_FREEMISS(cachep);
|
|
|
|
cache_flusharray(cachep, ac);
|
|
|
|
}
|
2011-08-26 16:26:17 +00:00
|
|
|
|
mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
When a user or administrator requires swap for their application, they
create a swap partition and file, format it with mkswap and activate it
with swapon. Swap over the network is considered as an option in diskless
systems. The two likely scenarios are when blade servers are used as part
of a cluster where the form factor or maintenance costs do not allow the
use of disks and thin clients.
The Linux Terminal Server Project recommends the use of the Network Block
Device (NBD) for swap according to the manual at
https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download
There is also documentation and tutorials on how to setup swap over NBD at
places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The
nbd-client also documents the use of NBD as swap. Despite this, the fact
is that a machine using NBD for swap can deadlock within minutes if swap
is used intensively. This patch series addresses the problem.
The core issue is that network block devices do not use mempools like
normal block devices do. As the host cannot control where they receive
packets from, they cannot reliably work out in advance how much memory
they might need. Some years ago, Peter Zijlstra developed a series of
patches that supported swap over an NFS that at least one distribution is
carrying within their kernels. This patch series borrows very heavily
from Peter's work to support swapping over NBD as a pre-requisite to
supporting swap-over-NFS. The bulk of the complexity is concerned with
preserving memory that is allocated from the PFMEMALLOC reserves for use
by the network layer which is needed for both NBD and NFS.
Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to
preserve access to pages allocated under low memory situations
to callers that are freeing memory.
Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks
Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC
reserves without setting PFMEMALLOC.
Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves
for later use by network packet processing.
Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required
Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set.
Patches 7-12 allows network processing to use PFMEMALLOC reserves when
the socket has been marked as being used by the VM to clean pages. If
packets are received and stored in pages that were allocated under
low-memory situations and are unrelated to the VM, the packets
are dropped.
Patch 11 reintroduces __skb_alloc_page which the networking
folk may object to but is needed in some cases to propogate
pfmemalloc from a newly allocated page to an skb. If there is a
strong objection, this patch can be dropped with the impact being
that swap-over-network will be slower in some cases but it should
not fail.
Patch 13 is a micro-optimisation to avoid a function call in the
common case.
Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use
PFMEMALLOC if necessary.
Patch 15 notes that it is still possible for the PFMEMALLOC reserve
to be depleted. To prevent this, direct reclaimers get throttled on
a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is
expected that kswapd and the direct reclaimers already running
will clean enough pages for the low watermark to be reached and
the throttled processes are woken up.
Patch 16 adds a statistic to track how often processes get throttled
Some basic performance testing was run using kernel builds, netperf on
loopback for UDP and TCP, hackbench (pipes and sockets), iozone and
sysbench. Each of them were expected to use the sl*b allocators
reasonably heavily but there did not appear to be significant performance
variances.
For testing swap-over-NBD, a machine was booted with 2G of RAM with a
swapfile backed by NBD. 8*NUM_CPU processes were started that create
anonymous memory mappings and read them linearly in a loop. The total
size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under
memory pressure.
Without the patches and using SLUB, the machine locks up within minutes
and runs to completion with them applied. With SLAB, the story is
different as an unpatched kernel run to completion. However, the patched
kernel completed the test 45% faster.
MICRO
3.5.0-rc2 3.5.0-rc2
vanilla swapnbd
Unrecognised test vmscan-anon-mmap-write
MMTests Statistics: duration
Sys Time Running Test (seconds) 197.80 173.07
User+Sys Time Running Test (seconds) 206.96 182.03
Total Elapsed Time (seconds) 3240.70 1762.09
This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages
Allocations of pages below the min watermark run a risk of the machine
hanging due to a lack of memory. To prevent this, only callers who have
PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are
allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to
a slab though, nothing prevents other callers consuming free objects
within those slabs. This patch limits access to slab pages that were
alloced from the PFMEMALLOC reserves.
When this patch is applied, pages allocated from below the low watermark
are returned with page->pfmemalloc set and it is up to the caller to
determine how the page should be protected. SLAB restricts access to any
page with page->pfmemalloc set to callers which are known to able to
access the PFMEMALLOC reserve. If one is not available, an attempt is
made to allocate a new page rather than use a reserve. SLUB is a bit more
relaxed in that it only records if the current per-CPU page was allocated
from PFMEMALLOC reserve and uses another partial slab if the caller does
not have the necessary GFP or process flags. This was found to be
sufficient in tests to avoid hangs due to SLUB generally maintaining
smaller lists than SLAB.
In low-memory conditions it does mean that !PFMEMALLOC allocators can fail
a slab allocation even though free objects are available because they are
being preserved for callers that are freeing pages.
[a.p.zijlstra@chello.nl: Original implementation]
[sebastian@breakpoint.cc: Correct order of page flag clearing]
Signed-off-by: Mel Gorman <mgorman@suse.de>
Cc: David Miller <davem@davemloft.net>
Cc: Neil Brown <neilb@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Eric B Munson <emunson@mgebm.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-07-31 23:43:58 +00:00
|
|
|
ac_put_obj(cachep, ac, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* kmem_cache_alloc - Allocate an object
|
|
|
|
* @cachep: The cache to allocate from.
|
|
|
|
* @flags: See kmalloc().
|
|
|
|
*
|
|
|
|
* Allocate an object from this cache. The flags are only relevant
|
|
|
|
* if the cache has no available objects.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-09-08 20:47:57 +00:00
|
|
|
void *ret = slab_alloc(cachep, flags, _RET_IP_);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
2009-03-23 13:12:24 +00:00
|
|
|
trace_kmem_cache_alloc(_RET_IP_, ret,
|
2012-06-13 15:24:58 +00:00
|
|
|
cachep->object_size, cachep->size, flags);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
|
|
|
return ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc);
|
|
|
|
|
2009-12-11 07:45:30 +00:00
|
|
|
#ifdef CONFIG_TRACING
|
2010-11-24 21:23:34 +00:00
|
|
|
void *
|
2012-09-08 20:47:56 +00:00
|
|
|
kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size)
|
2008-08-10 17:14:05 +00:00
|
|
|
{
|
2010-11-24 21:23:34 +00:00
|
|
|
void *ret;
|
|
|
|
|
2012-09-08 20:47:57 +00:00
|
|
|
ret = slab_alloc(cachep, flags, _RET_IP_);
|
2010-11-24 21:23:34 +00:00
|
|
|
|
|
|
|
trace_kmalloc(_RET_IP_, ret,
|
2012-09-08 20:47:52 +00:00
|
|
|
size, cachep->size, flags);
|
2010-11-24 21:23:34 +00:00
|
|
|
return ret;
|
2008-08-10 17:14:05 +00:00
|
|
|
}
|
2010-11-24 21:23:34 +00:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_trace);
|
2008-08-10 17:14:05 +00:00
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#ifdef CONFIG_NUMA
|
2006-12-07 04:32:30 +00:00
|
|
|
void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
|
|
|
|
{
|
2012-09-08 20:47:57 +00:00
|
|
|
void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
2009-03-23 13:12:24 +00:00
|
|
|
trace_kmem_cache_alloc_node(_RET_IP_, ret,
|
2012-06-13 15:24:58 +00:00
|
|
|
cachep->object_size, cachep->size,
|
2009-03-23 13:12:24 +00:00
|
|
|
flags, nodeid);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
|
|
|
return ret;
|
2006-12-07 04:32:30 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_node);
|
|
|
|
|
2009-12-11 07:45:30 +00:00
|
|
|
#ifdef CONFIG_TRACING
|
2012-09-08 20:47:56 +00:00
|
|
|
void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep,
|
2010-11-24 21:23:34 +00:00
|
|
|
gfp_t flags,
|
2012-09-08 20:47:56 +00:00
|
|
|
int nodeid,
|
|
|
|
size_t size)
|
2008-08-10 17:14:05 +00:00
|
|
|
{
|
2010-11-24 21:23:34 +00:00
|
|
|
void *ret;
|
|
|
|
|
2012-09-25 11:07:08 +00:00
|
|
|
ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
|
2012-09-08 20:47:55 +00:00
|
|
|
|
2010-11-24 21:23:34 +00:00
|
|
|
trace_kmalloc_node(_RET_IP_, ret,
|
2012-09-08 20:47:52 +00:00
|
|
|
size, cachep->size,
|
2010-11-24 21:23:34 +00:00
|
|
|
flags, nodeid);
|
|
|
|
return ret;
|
2008-08-10 17:14:05 +00:00
|
|
|
}
|
2010-11-24 21:23:34 +00:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
|
2008-08-10 17:14:05 +00:00
|
|
|
#endif
|
|
|
|
|
2006-12-07 04:32:30 +00:00
|
|
|
static __always_inline void *
|
2012-09-08 20:47:55 +00:00
|
|
|
__do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)
|
2005-05-01 15:58:38 +00:00
|
|
|
{
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep;
|
2005-05-01 15:58:38 +00:00
|
|
|
|
|
|
|
cachep = kmem_find_general_cachep(size, flags);
|
2007-07-17 11:03:22 +00:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(cachep)))
|
|
|
|
return cachep;
|
2012-09-08 20:47:56 +00:00
|
|
|
return kmem_cache_alloc_node_trace(cachep, flags, node, size);
|
2005-05-01 15:58:38 +00:00
|
|
|
}
|
2006-12-07 04:32:30 +00:00
|
|
|
|
2009-12-11 07:45:50 +00:00
|
|
|
#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
|
2006-12-07 04:32:30 +00:00
|
|
|
void *__kmalloc_node(size_t size, gfp_t flags, int node)
|
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc_node(size, flags, node, _RET_IP_);
|
2006-12-07 04:32:30 +00:00
|
|
|
}
|
2006-09-26 06:31:36 +00:00
|
|
|
EXPORT_SYMBOL(__kmalloc_node);
|
2006-12-07 04:32:30 +00:00
|
|
|
|
|
|
|
void *__kmalloc_node_track_caller(size_t size, gfp_t flags,
|
2008-08-19 17:43:25 +00:00
|
|
|
int node, unsigned long caller)
|
2006-12-07 04:32:30 +00:00
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc_node(size, flags, node, caller);
|
2006-12-07 04:32:30 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_node_track_caller);
|
|
|
|
#else
|
|
|
|
void *__kmalloc_node(size_t size, gfp_t flags, int node)
|
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc_node(size, flags, node, 0);
|
2006-12-07 04:32:30 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_node);
|
2009-12-11 07:45:50 +00:00
|
|
|
#endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */
|
2006-12-07 04:32:30 +00:00
|
|
|
#endif /* CONFIG_NUMA */
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
2006-06-23 09:03:48 +00:00
|
|
|
* __do_kmalloc - allocate memory
|
2005-04-16 22:20:36 +00:00
|
|
|
* @size: how many bytes of memory are required.
|
2006-06-23 09:03:48 +00:00
|
|
|
* @flags: the type of memory to allocate (see kmalloc).
|
2006-03-22 08:08:14 +00:00
|
|
|
* @caller: function caller for debug tracking of the caller
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2006-02-01 11:05:52 +00:00
|
|
|
static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
|
2012-09-08 20:47:55 +00:00
|
|
|
unsigned long caller)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep;
|
2008-08-10 17:14:05 +00:00
|
|
|
void *ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-05-01 15:58:38 +00:00
|
|
|
/* If you want to save a few bytes .text space: replace
|
|
|
|
* __ with kmem_.
|
|
|
|
* Then kmalloc uses the uninlined functions instead of the inline
|
|
|
|
* functions.
|
|
|
|
*/
|
|
|
|
cachep = __find_general_cachep(size, flags);
|
2007-07-19 20:17:15 +00:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(cachep)))
|
|
|
|
return cachep;
|
2012-09-08 20:47:57 +00:00
|
|
|
ret = slab_alloc(cachep, flags, caller);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
2012-09-08 20:47:55 +00:00
|
|
|
trace_kmalloc(caller, ret,
|
2012-06-13 15:24:57 +00:00
|
|
|
size, cachep->size, flags);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
|
|
|
return ret;
|
2006-02-01 11:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-11 07:45:50 +00:00
|
|
|
#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
|
2006-02-01 11:05:52 +00:00
|
|
|
void *__kmalloc(size_t size, gfp_t flags)
|
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc(size, flags, _RET_IP_);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc);
|
|
|
|
|
2008-08-19 17:43:25 +00:00
|
|
|
void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
|
2006-02-01 11:05:52 +00:00
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc(size, flags, caller);
|
2006-02-01 11:05:52 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_track_caller);
|
2006-10-04 09:15:25 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
void *__kmalloc(size_t size, gfp_t flags)
|
|
|
|
{
|
2012-09-08 20:47:55 +00:00
|
|
|
return __do_kmalloc(size, flags, 0);
|
2006-10-04 09:15:25 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc);
|
2006-02-01 11:05:52 +00:00
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* kmem_cache_free - Deallocate an object
|
|
|
|
* @cachep: The cache the allocation was from.
|
|
|
|
* @objp: The previously allocated object.
|
|
|
|
*
|
|
|
|
* Free an object which was previously allocated from this
|
|
|
|
* cache.
|
|
|
|
*/
|
2006-02-01 11:05:50 +00:00
|
|
|
void kmem_cache_free(struct kmem_cache *cachep, void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
2012-12-18 22:22:46 +00:00
|
|
|
cachep = cache_from_obj(cachep, objp);
|
|
|
|
if (!cachep)
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
local_irq_save(flags);
|
2012-07-02 06:29:10 +00:00
|
|
|
debug_check_no_locks_freed(objp, cachep->object_size);
|
2008-04-30 07:55:01 +00:00
|
|
|
if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
|
2012-06-13 15:24:58 +00:00
|
|
|
debug_check_no_obj_freed(objp, cachep->object_size);
|
2012-09-08 20:47:55 +00:00
|
|
|
__cache_free(cachep, objp, _RET_IP_);
|
2005-04-16 22:20:36 +00:00
|
|
|
local_irq_restore(flags);
|
2008-08-10 17:14:05 +00:00
|
|
|
|
2009-03-23 13:12:24 +00:00
|
|
|
trace_kmem_cache_free(_RET_IP_, objp);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_free);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* kfree - free previously allocated memory
|
|
|
|
* @objp: pointer returned by kmalloc.
|
|
|
|
*
|
2005-09-09 20:10:16 +00:00
|
|
|
* If @objp is NULL, no operation is performed.
|
|
|
|
*
|
2005-04-16 22:20:36 +00:00
|
|
|
* Don't free memory not originally allocated by kmalloc()
|
|
|
|
* or you will run into trouble.
|
|
|
|
*/
|
|
|
|
void kfree(const void *objp)
|
|
|
|
{
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *c;
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
2009-03-25 09:05:57 +00:00
|
|
|
trace_kfree(_RET_IP_, objp);
|
|
|
|
|
2007-07-17 11:03:22 +00:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(objp)))
|
2005-04-16 22:20:36 +00:00
|
|
|
return;
|
|
|
|
local_irq_save(flags);
|
|
|
|
kfree_debugcheck(objp);
|
2006-02-01 11:05:49 +00:00
|
|
|
c = virt_to_cache(objp);
|
2012-06-13 15:24:58 +00:00
|
|
|
debug_check_no_locks_freed(objp, c->object_size);
|
|
|
|
|
|
|
|
debug_check_no_obj_freed(objp, c->object_size);
|
2012-09-08 20:47:55 +00:00
|
|
|
__cache_free(c, (void *)objp, _RET_IP_);
|
2005-04-16 22:20:36 +00:00
|
|
|
local_irq_restore(flags);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kfree);
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
/*
|
2007-10-19 23:27:18 +00:00
|
|
|
* This initializes kmem_list3 or resizes various caches for all nodes.
|
2005-09-09 20:03:32 +00:00
|
|
|
*/
|
2009-06-10 16:40:04 +00:00
|
|
|
static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp)
|
2005-09-09 20:03:32 +00:00
|
|
|
{
|
|
|
|
int node;
|
|
|
|
struct kmem_list3 *l3;
|
2006-03-25 11:06:46 +00:00
|
|
|
struct array_cache *new_shared;
|
2006-12-07 04:32:16 +00:00
|
|
|
struct array_cache **new_alien = NULL;
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2008-01-24 13:49:54 +00:00
|
|
|
for_each_online_node(node) {
|
2006-03-25 11:06:46 +00:00
|
|
|
|
2006-12-07 04:32:16 +00:00
|
|
|
if (use_alien_caches) {
|
2009-06-10 16:40:04 +00:00
|
|
|
new_alien = alloc_alien_cache(node, cachep->limit, gfp);
|
2006-12-07 04:32:16 +00:00
|
|
|
if (!new_alien)
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 11:06:46 +00:00
|
|
|
|
2007-05-06 21:49:28 +00:00
|
|
|
new_shared = NULL;
|
|
|
|
if (cachep->shared) {
|
|
|
|
new_shared = alloc_arraycache(node,
|
2006-03-25 11:06:47 +00:00
|
|
|
cachep->shared*cachep->batchcount,
|
2009-06-10 16:40:04 +00:00
|
|
|
0xbaadf00d, gfp);
|
2007-05-06 21:49:28 +00:00
|
|
|
if (!new_shared) {
|
|
|
|
free_alien_cache(new_alien);
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 11:06:47 +00:00
|
|
|
}
|
2006-03-25 11:06:46 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (l3) {
|
2006-03-25 11:06:46 +00:00
|
|
|
struct array_cache *shared = l3->shared;
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
|
|
|
|
2006-03-25 11:06:46 +00:00
|
|
|
if (shared)
|
2006-03-25 11:06:47 +00:00
|
|
|
free_block(cachep, shared->entry,
|
|
|
|
shared->avail, node);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-03-25 11:06:46 +00:00
|
|
|
l3->shared = new_shared;
|
|
|
|
if (!l3->alien) {
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->alien = new_alien;
|
|
|
|
new_alien = NULL;
|
|
|
|
}
|
2006-01-08 09:00:37 +00:00
|
|
|
l3->free_limit = (1 + nr_cpus_node(node)) *
|
2006-03-22 08:08:11 +00:00
|
|
|
cachep->batchcount + cachep->num;
|
2005-09-09 20:03:32 +00:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2006-03-25 11:06:46 +00:00
|
|
|
kfree(shared);
|
2005-09-09 20:03:32 +00:00
|
|
|
free_alien_cache(new_alien);
|
|
|
|
continue;
|
|
|
|
}
|
2009-06-10 16:40:04 +00:00
|
|
|
l3 = kmalloc_node(sizeof(struct kmem_list3), gfp, node);
|
2006-03-25 11:06:47 +00:00
|
|
|
if (!l3) {
|
|
|
|
free_alien_cache(new_alien);
|
|
|
|
kfree(new_shared);
|
2005-09-09 20:03:32 +00:00
|
|
|
goto fail;
|
2006-03-25 11:06:47 +00:00
|
|
|
}
|
2005-09-09 20:03:32 +00:00
|
|
|
|
|
|
|
kmem_list3_init(l3);
|
|
|
|
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
|
2006-03-22 08:08:11 +00:00
|
|
|
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
|
2006-03-25 11:06:46 +00:00
|
|
|
l3->shared = new_shared;
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->alien = new_alien;
|
2006-01-08 09:00:37 +00:00
|
|
|
l3->free_limit = (1 + nr_cpus_node(node)) *
|
2006-03-22 08:08:11 +00:00
|
|
|
cachep->batchcount + cachep->num;
|
2005-09-09 20:03:32 +00:00
|
|
|
cachep->nodelists[node] = l3;
|
|
|
|
}
|
2006-03-25 11:06:46 +00:00
|
|
|
return 0;
|
2006-03-25 11:06:47 +00:00
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
fail:
|
2012-06-13 15:24:57 +00:00
|
|
|
if (!cachep->list.next) {
|
2006-03-25 11:06:47 +00:00
|
|
|
/* Cache is not active yet. Roll back what we did */
|
|
|
|
node--;
|
|
|
|
while (node >= 0) {
|
|
|
|
if (cachep->nodelists[node]) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
|
|
|
|
kfree(l3->shared);
|
|
|
|
free_alien_cache(l3->alien);
|
|
|
|
kfree(l3);
|
|
|
|
cachep->nodelists[node] = NULL;
|
|
|
|
}
|
|
|
|
node--;
|
|
|
|
}
|
|
|
|
}
|
2006-03-25 11:06:46 +00:00
|
|
|
return -ENOMEM;
|
2005-09-09 20:03:32 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
struct ccupdate_struct {
|
2006-02-01 11:05:50 +00:00
|
|
|
struct kmem_cache *cachep;
|
2011-07-25 06:55:42 +00:00
|
|
|
struct array_cache *new[0];
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void do_ccupdate_local(void *info)
|
|
|
|
{
|
2006-03-22 08:08:11 +00:00
|
|
|
struct ccupdate_struct *new = info;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct array_cache *old;
|
|
|
|
|
|
|
|
check_irq_off();
|
2006-02-01 11:05:49 +00:00
|
|
|
old = cpu_cache_get(new->cachep);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
|
|
|
|
new->new[smp_processor_id()] = old;
|
|
|
|
}
|
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
/* Always called with the slab_mutex held */
|
2012-12-18 22:23:03 +00:00
|
|
|
static int __do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
2009-06-10 16:40:04 +00:00
|
|
|
int batchcount, int shared, gfp_t gfp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-09-26 06:31:47 +00:00
|
|
|
struct ccupdate_struct *new;
|
2006-09-26 06:31:38 +00:00
|
|
|
int i;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-07-25 06:55:42 +00:00
|
|
|
new = kzalloc(sizeof(*new) + nr_cpu_ids * sizeof(struct array_cache *),
|
|
|
|
gfp);
|
2006-09-26 06:31:47 +00:00
|
|
|
if (!new)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
for_each_online_cpu(i) {
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
new->new[i] = alloc_arraycache(cpu_to_mem(i), limit,
|
2009-06-10 16:40:04 +00:00
|
|
|
batchcount, gfp);
|
2006-09-26 06:31:47 +00:00
|
|
|
if (!new->new[i]) {
|
2006-01-08 09:00:37 +00:00
|
|
|
for (i--; i >= 0; i--)
|
2006-09-26 06:31:47 +00:00
|
|
|
kfree(new->new[i]);
|
|
|
|
kfree(new);
|
2005-09-09 20:03:32 +00:00
|
|
|
return -ENOMEM;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-26 06:31:47 +00:00
|
|
|
new->cachep = cachep;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-05-09 07:39:44 +00:00
|
|
|
on_each_cpu(do_ccupdate_local, (void *)new, 1);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
check_irq_on();
|
|
|
|
cachep->batchcount = batchcount;
|
|
|
|
cachep->limit = limit;
|
2005-09-09 20:03:32 +00:00
|
|
|
cachep->shared = shared;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
for_each_online_cpu(i) {
|
2006-09-26 06:31:47 +00:00
|
|
|
struct array_cache *ccold = new->new[i];
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!ccold)
|
|
|
|
continue;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
spin_lock_irq(&cachep->nodelists[cpu_to_mem(i)]->list_lock);
|
|
|
|
free_block(cachep, ccold->entry, ccold->avail, cpu_to_mem(i));
|
|
|
|
spin_unlock_irq(&cachep->nodelists[cpu_to_mem(i)]->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
kfree(ccold);
|
|
|
|
}
|
2006-09-26 06:31:47 +00:00
|
|
|
kfree(new);
|
2009-06-10 16:40:04 +00:00
|
|
|
return alloc_kmemlist(cachep, gfp);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-12-18 22:23:03 +00:00
|
|
|
static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
|
|
|
int batchcount, int shared, gfp_t gfp)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct kmem_cache *c = NULL;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
|
|
|
|
|
|
|
|
if (slab_state < FULL)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if ((ret < 0) || !is_root_cache(cachep))
|
|
|
|
return ret;
|
|
|
|
|
2012-12-18 22:23:10 +00:00
|
|
|
VM_BUG_ON(!mutex_is_locked(&slab_mutex));
|
2012-12-18 22:23:03 +00:00
|
|
|
for_each_memcg_cache_index(i) {
|
|
|
|
c = cache_from_memcg(cachep, i);
|
|
|
|
if (c)
|
|
|
|
/* return value determined by the parent cache only */
|
|
|
|
__do_tune_cpucache(c, limit, batchcount, shared, gfp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
/* Called with slab_mutex held always */
|
2009-06-10 16:40:04 +00:00
|
|
|
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int err;
|
2012-12-18 22:23:03 +00:00
|
|
|
int limit = 0;
|
|
|
|
int shared = 0;
|
|
|
|
int batchcount = 0;
|
|
|
|
|
|
|
|
if (!is_root_cache(cachep)) {
|
|
|
|
struct kmem_cache *root = memcg_root_cache(cachep);
|
|
|
|
limit = root->limit;
|
|
|
|
shared = root->shared;
|
|
|
|
batchcount = root->batchcount;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-12-18 22:23:03 +00:00
|
|
|
if (limit && shared && batchcount)
|
|
|
|
goto skip_setup;
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* The head array serves three purposes:
|
2005-04-16 22:20:36 +00:00
|
|
|
* - create a LIFO ordering, i.e. return objects that are cache-warm
|
|
|
|
* - reduce the number of spinlock operations.
|
2006-03-22 08:08:11 +00:00
|
|
|
* - reduce the number of linked list operations on the slab and
|
2005-04-16 22:20:36 +00:00
|
|
|
* bufctl chains: array operations are cheaper.
|
|
|
|
* The numbers are guessed, we should auto-tune as described by
|
|
|
|
* Bonwick.
|
|
|
|
*/
|
2012-06-13 15:24:57 +00:00
|
|
|
if (cachep->size > 131072)
|
2005-04-16 22:20:36 +00:00
|
|
|
limit = 1;
|
2012-06-13 15:24:57 +00:00
|
|
|
else if (cachep->size > PAGE_SIZE)
|
2005-04-16 22:20:36 +00:00
|
|
|
limit = 8;
|
2012-06-13 15:24:57 +00:00
|
|
|
else if (cachep->size > 1024)
|
2005-04-16 22:20:36 +00:00
|
|
|
limit = 24;
|
2012-06-13 15:24:57 +00:00
|
|
|
else if (cachep->size > 256)
|
2005-04-16 22:20:36 +00:00
|
|
|
limit = 54;
|
|
|
|
else
|
|
|
|
limit = 120;
|
|
|
|
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* CPU bound tasks (e.g. network routing) can exhibit cpu bound
|
2005-04-16 22:20:36 +00:00
|
|
|
* allocation behaviour: Most allocs on one cpu, most free operations
|
|
|
|
* on another cpu. For these cases, an efficient object passing between
|
|
|
|
* cpus is necessary. This is provided by a shared array. The array
|
|
|
|
* replaces Bonwick's magazine layer.
|
|
|
|
* On uniprocessor, it's functionally equivalent (but less efficient)
|
|
|
|
* to a larger limit. Thus disabled by default.
|
|
|
|
*/
|
|
|
|
shared = 0;
|
2012-06-13 15:24:57 +00:00
|
|
|
if (cachep->size <= PAGE_SIZE && num_possible_cpus() > 1)
|
2005-04-16 22:20:36 +00:00
|
|
|
shared = 8;
|
|
|
|
|
|
|
|
#if DEBUG
|
2006-03-22 08:08:11 +00:00
|
|
|
/*
|
|
|
|
* With debugging enabled, large batchcount lead to excessively long
|
|
|
|
* periods with disabled local interrupts. Limit the batchcount
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
if (limit > 32)
|
|
|
|
limit = 32;
|
|
|
|
#endif
|
2012-12-18 22:23:03 +00:00
|
|
|
batchcount = (limit + 1) / 2;
|
|
|
|
skip_setup:
|
|
|
|
err = do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (err)
|
|
|
|
printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
|
2006-01-08 09:00:37 +00:00
|
|
|
cachep->name, -err);
|
2006-09-26 06:31:38 +00:00
|
|
|
return err;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-22 08:09:07 +00:00
|
|
|
/*
|
|
|
|
* Drain an array if it contains any elements taking the l3 lock only if
|
2006-03-22 08:09:07 +00:00
|
|
|
* necessary. Note that the l3 listlock also protects the array_cache
|
|
|
|
* if drain_array() is used on the shared array.
|
2006-03-22 08:09:07 +00:00
|
|
|
*/
|
2011-01-11 23:49:32 +00:00
|
|
|
static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
|
2006-03-22 08:09:07 +00:00
|
|
|
struct array_cache *ac, int force, int node)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
int tofree;
|
|
|
|
|
2006-03-22 08:09:07 +00:00
|
|
|
if (!ac || !ac->avail)
|
|
|
|
return;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (ac->touched && !force) {
|
|
|
|
ac->touched = 0;
|
2006-03-22 08:09:07 +00:00
|
|
|
} else {
|
2006-03-22 08:09:07 +00:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
2006-03-22 08:09:07 +00:00
|
|
|
if (ac->avail) {
|
|
|
|
tofree = force ? ac->avail : (ac->limit + 4) / 5;
|
|
|
|
if (tofree > ac->avail)
|
|
|
|
tofree = (ac->avail + 1) / 2;
|
|
|
|
free_block(cachep, ac->entry, tofree, node);
|
|
|
|
ac->avail -= tofree;
|
|
|
|
memmove(ac->entry, &(ac->entry[tofree]),
|
|
|
|
sizeof(void *) * ac->avail);
|
|
|
|
}
|
2006-03-22 08:09:07 +00:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cache_reap - Reclaim memory from caches.
|
2007-03-01 04:12:13 +00:00
|
|
|
* @w: work descriptor
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Called from workqueue/eventd every few seconds.
|
|
|
|
* Purpose:
|
|
|
|
* - clear the per-cpu caches for this CPU.
|
|
|
|
* - return freeable pages to the main free memory pool.
|
|
|
|
*
|
2006-03-22 08:08:11 +00:00
|
|
|
* If we cannot acquire the cache chain mutex then just give up - we'll try
|
|
|
|
* again on the next iteration.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2007-02-10 09:42:55 +00:00
|
|
|
static void cache_reap(struct work_struct *w)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-06-23 09:03:17 +00:00
|
|
|
struct kmem_cache *searchp;
|
2005-09-09 20:03:32 +00:00
|
|
|
struct kmem_list3 *l3;
|
numa: slab: use numa_mem_id() for slab local memory node
Example usage of generic "numa_mem_id()":
The mainline slab code, since ~ 2.6.19, does not handle memoryless nodes
well. Specifically, the "fast path"--____cache_alloc()--will never
succeed as slab doesn't cache offnode object on the per cpu queues, and
for memoryless nodes, all memory will be "off node" relative to
numa_node_id(). This adds significant overhead to all kmem cache
allocations, incurring a significant regression relative to earlier
kernels [from before slab.c was reorganized].
This patch uses the generic topology function "numa_mem_id()" to return
the "effective local memory node" for the calling context. This is the
first node in the local node's generic fallback zonelist-- the same node
that "local" mempolicy-based allocations would use. This lets slab cache
these "local" allocations and avoid fallback/refill on every allocation.
N.B.: Slab will need to handle node and memory hotplug events that could
change the value returned by numa_mem_id() for any given node if recent
changes to address memory hotplug don't already address this. E.g., flush
all per cpu slab queues before rebuilding the zonelists while the
"machine" is held in the stopped state.
Performance impact on "hackbench 400 process 200"
2.6.34-rc3-mmotm-100405-1609 no-patch this-patch
ia64 no memoryless nodes [avg of 10]: 11.713 11.637 ~0.65 diff
ia64 cpus all on memless nodes [10]: 228.259 26.484 ~8.6x speedup
The slowdown of the patched kernel from ~12 sec to ~28 seconds when
configured with memoryless nodes is the result of all cpus allocating from
a single node's mm pagepool. The cache lines of the single node are
distributed/interleaved over the memory of the real physical nodes, but
the zone lock, list heads, ... of the single node with memory still each
live in a single cache line that is accessed from all processors.
x86_64 [8x6 AMD] [avg of 40]: 2.883 2.845
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Eric Whitney <eric.whitney@hp.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-26 21:45:03 +00:00
|
|
|
int node = numa_mem_id();
|
2009-04-02 23:56:54 +00:00
|
|
|
struct delayed_work *work = to_delayed_work(w);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
if (!mutex_trylock(&slab_mutex))
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Give up. Setup the next iteration. */
|
2007-02-10 09:42:55 +00:00
|
|
|
goto out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(searchp, &slab_caches, list) {
|
2005-04-16 22:20:36 +00:00
|
|
|
check_irq_on();
|
|
|
|
|
2006-03-22 08:09:05 +00:00
|
|
|
/*
|
|
|
|
* We only take the l3 lock if absolutely necessary and we
|
|
|
|
* have established with reasonable certainty that
|
|
|
|
* we can do some work if the lock was obtained.
|
|
|
|
*/
|
2006-03-22 08:09:06 +00:00
|
|
|
l3 = searchp->nodelists[node];
|
2006-03-22 08:09:05 +00:00
|
|
|
|
2006-03-10 01:33:54 +00:00
|
|
|
reap_alien(searchp, l3);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:09:06 +00:00
|
|
|
drain_array(searchp, l3, cpu_cache_get(searchp), 0, node);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:09:05 +00:00
|
|
|
/*
|
|
|
|
* These are racy checks but it does not matter
|
|
|
|
* if we skip one check or scan twice.
|
|
|
|
*/
|
2005-09-09 20:03:32 +00:00
|
|
|
if (time_after(l3->next_reap, jiffies))
|
2006-03-22 08:09:05 +00:00
|
|
|
goto next;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->next_reap = jiffies + REAPTIMEOUT_LIST3;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-03-22 08:09:06 +00:00
|
|
|
drain_array(searchp, l3, l3->shared, 0, node);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
if (l3->free_touched)
|
2005-09-09 20:03:32 +00:00
|
|
|
l3->free_touched = 0;
|
2006-06-30 08:55:45 +00:00
|
|
|
else {
|
|
|
|
int freed;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-06-30 08:55:45 +00:00
|
|
|
freed = drain_freelist(searchp, l3, (l3->free_limit +
|
|
|
|
5 * searchp->num - 1) / (5 * searchp->num));
|
|
|
|
STATS_ADD_REAPED(searchp, freed);
|
|
|
|
}
|
2006-03-22 08:09:05 +00:00
|
|
|
next:
|
2005-04-16 22:20:36 +00:00
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
check_irq_on();
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2006-03-10 01:33:54 +00:00
|
|
|
next_reap_node();
|
2007-02-10 09:42:55 +00:00
|
|
|
out:
|
2006-03-22 08:08:11 +00:00
|
|
|
/* Set up the next iteration */
|
2007-02-10 09:42:55 +00:00
|
|
|
schedule_delayed_work(work, round_jiffies_relative(REAPTIMEOUT_CPUC));
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2008-01-02 21:04:48 +00:00
|
|
|
#ifdef CONFIG_SLABINFO
|
2012-10-19 14:20:27 +00:00
|
|
|
void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
unsigned long active_objs;
|
|
|
|
unsigned long num_objs;
|
|
|
|
unsigned long active_slabs = 0;
|
|
|
|
unsigned long num_slabs, free_objects = 0, shared_avail = 0;
|
2005-09-09 20:03:32 +00:00
|
|
|
const char *name;
|
2005-04-16 22:20:36 +00:00
|
|
|
char *error = NULL;
|
2005-09-09 20:03:32 +00:00
|
|
|
int node;
|
|
|
|
struct kmem_list3 *l3;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
active_objs = 0;
|
|
|
|
num_slabs = 0;
|
2005-09-09 20:03:32 +00:00
|
|
|
for_each_online_node(node) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
2006-02-05 07:27:58 +00:00
|
|
|
check_irq_on();
|
|
|
|
spin_lock_irq(&l3->list_lock);
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-06-23 09:03:17 +00:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list) {
|
2005-09-09 20:03:32 +00:00
|
|
|
if (slabp->inuse != cachep->num && !error)
|
|
|
|
error = "slabs_full accounting error";
|
|
|
|
active_objs += cachep->num;
|
|
|
|
active_slabs++;
|
|
|
|
}
|
2006-06-23 09:03:17 +00:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list) {
|
2005-09-09 20:03:32 +00:00
|
|
|
if (slabp->inuse == cachep->num && !error)
|
|
|
|
error = "slabs_partial inuse accounting error";
|
|
|
|
if (!slabp->inuse && !error)
|
|
|
|
error = "slabs_partial/inuse accounting error";
|
|
|
|
active_objs += slabp->inuse;
|
|
|
|
active_slabs++;
|
|
|
|
}
|
2006-06-23 09:03:17 +00:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_free, list) {
|
2005-09-09 20:03:32 +00:00
|
|
|
if (slabp->inuse && !error)
|
|
|
|
error = "slabs_free/inuse accounting error";
|
|
|
|
num_slabs++;
|
|
|
|
}
|
|
|
|
free_objects += l3->free_objects;
|
[PATCH] NUMA slab locking fixes: fix cpu down and up locking
This fixes locking and bugs in cpu_down and cpu_up paths of the NUMA slab
allocator. Sonny Rao <sonny@burdell.org> reported problems sometime back on
POWER5 boxes, when the last cpu on the nodes were being offlined. We could
not reproduce the same on x86_64 because the cpumask (node_to_cpumask) was not
being updated on cpu down. Since that issue is now fixed, we can reproduce
Sonny's problems on x86_64 NUMA, and here is the fix.
The problem earlier was on CPU_DOWN, if it was the last cpu on the node to go
down, the array_caches (shared, alien) and the kmem_list3 of the node were
being freed (kfree) with the kmem_list3 lock held. If the l3 or the
array_caches were to come from the same cache being cleared, we hit on
badness.
This patch cleans up the locking in cpu_up and cpu_down path. We cannot
really free l3 on cpu down because, there is no node offlining yet and even
though a cpu is not yet up, node local memory can be allocated for it. So l3s
are usually allocated at keme_cache_create and destroyed at
kmem_cache_destroy. Hence, we don't need cachep->spinlock protection to get
to the cachep->nodelist[nodeid] either.
Patch survived onlining and offlining on a 4 core 2 node Tyan box with a 4
dbench process running all the time.
Signed-off-by: Alok N Kataria <alokk@calsoftinc.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Cc: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-02-05 07:27:59 +00:00
|
|
|
if (l3->shared)
|
|
|
|
shared_avail += l3->shared->avail;
|
2005-09-09 20:03:32 +00:00
|
|
|
|
2006-02-05 07:27:58 +00:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-01-08 09:00:37 +00:00
|
|
|
num_slabs += active_slabs;
|
|
|
|
num_objs = num_slabs * cachep->num;
|
2005-09-09 20:03:32 +00:00
|
|
|
if (num_objs - active_objs != free_objects && !error)
|
2005-04-16 22:20:36 +00:00
|
|
|
error = "free_objects accounting error";
|
|
|
|
|
2006-01-08 09:00:37 +00:00
|
|
|
name = cachep->name;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
|
|
|
|
|
2012-10-19 14:20:27 +00:00
|
|
|
sinfo->active_objs = active_objs;
|
|
|
|
sinfo->num_objs = num_objs;
|
|
|
|
sinfo->active_slabs = active_slabs;
|
|
|
|
sinfo->num_slabs = num_slabs;
|
|
|
|
sinfo->shared_avail = shared_avail;
|
|
|
|
sinfo->limit = cachep->limit;
|
|
|
|
sinfo->batchcount = cachep->batchcount;
|
|
|
|
sinfo->shared = cachep->shared;
|
|
|
|
sinfo->objects_per_slab = cachep->num;
|
|
|
|
sinfo->cache_order = cachep->gfporder;
|
|
|
|
}
|
|
|
|
|
|
|
|
void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
|
|
|
|
{
|
2005-04-16 22:20:36 +00:00
|
|
|
#if STATS
|
2006-01-08 09:00:37 +00:00
|
|
|
{ /* list3 stats */
|
2005-04-16 22:20:36 +00:00
|
|
|
unsigned long high = cachep->high_mark;
|
|
|
|
unsigned long allocs = cachep->num_allocations;
|
|
|
|
unsigned long grown = cachep->grown;
|
|
|
|
unsigned long reaped = cachep->reaped;
|
|
|
|
unsigned long errors = cachep->errors;
|
|
|
|
unsigned long max_freeable = cachep->max_freeable;
|
|
|
|
unsigned long node_allocs = cachep->node_allocs;
|
2005-09-09 20:03:32 +00:00
|
|
|
unsigned long node_frees = cachep->node_frees;
|
2006-04-11 05:52:54 +00:00
|
|
|
unsigned long overflows = cachep->node_overflow;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-03-27 02:27:58 +00:00
|
|
|
seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu "
|
|
|
|
"%4lu %4lu %4lu %4lu %4lu",
|
|
|
|
allocs, high, grown,
|
|
|
|
reaped, errors, max_freeable, node_allocs,
|
|
|
|
node_frees, overflows);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
/* cpu stats */
|
|
|
|
{
|
|
|
|
unsigned long allochit = atomic_read(&cachep->allochit);
|
|
|
|
unsigned long allocmiss = atomic_read(&cachep->allocmiss);
|
|
|
|
unsigned long freehit = atomic_read(&cachep->freehit);
|
|
|
|
unsigned long freemiss = atomic_read(&cachep->freemiss);
|
|
|
|
|
|
|
|
seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu",
|
2006-01-08 09:00:37 +00:00
|
|
|
allochit, allocmiss, freehit, freemiss);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_SLABINFO_WRITE 128
|
|
|
|
/**
|
|
|
|
* slabinfo_write - Tuning for the slab allocator
|
|
|
|
* @file: unused
|
|
|
|
* @buffer: user buffer
|
|
|
|
* @count: data length
|
|
|
|
* @ppos: unused
|
|
|
|
*/
|
2012-10-19 14:20:25 +00:00
|
|
|
ssize_t slabinfo_write(struct file *file, const char __user *buffer,
|
2006-01-08 09:00:37 +00:00
|
|
|
size_t count, loff_t *ppos)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-01-08 09:00:37 +00:00
|
|
|
char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
|
2005-04-16 22:20:36 +00:00
|
|
|
int limit, batchcount, shared, res;
|
2006-06-23 09:03:17 +00:00
|
|
|
struct kmem_cache *cachep;
|
2006-01-08 09:00:37 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (count > MAX_SLABINFO_WRITE)
|
|
|
|
return -EINVAL;
|
|
|
|
if (copy_from_user(&kbuf, buffer, count))
|
|
|
|
return -EFAULT;
|
2006-01-08 09:00:37 +00:00
|
|
|
kbuf[MAX_SLABINFO_WRITE] = '\0';
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
tmp = strchr(kbuf, ' ');
|
|
|
|
if (!tmp)
|
|
|
|
return -EINVAL;
|
|
|
|
*tmp = '\0';
|
|
|
|
tmp++;
|
|
|
|
if (sscanf(tmp, " %d %d %d", &limit, &batchcount, &shared) != 3)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Find the cache in the chain of caches. */
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2005-04-16 22:20:36 +00:00
|
|
|
res = -EINVAL;
|
2012-07-06 20:25:12 +00:00
|
|
|
list_for_each_entry(cachep, &slab_caches, list) {
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!strcmp(cachep->name, kbuf)) {
|
2006-03-22 08:08:11 +00:00
|
|
|
if (limit < 1 || batchcount < 1 ||
|
|
|
|
batchcount > limit || shared < 0) {
|
2005-09-09 20:03:32 +00:00
|
|
|
res = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
2005-09-09 20:03:32 +00:00
|
|
|
res = do_tune_cpucache(cachep, limit,
|
2009-06-10 16:40:04 +00:00
|
|
|
batchcount, shared,
|
|
|
|
GFP_KERNEL);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (res >= 0)
|
|
|
|
res = count;
|
|
|
|
return res;
|
|
|
|
}
|
2006-03-25 11:06:39 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
|
|
|
|
static void *leaks_start(struct seq_file *m, loff_t *pos)
|
|
|
|
{
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
|
|
|
return seq_list_start(&slab_caches, *pos);
|
2006-03-25 11:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int add_caller(unsigned long *n, unsigned long v)
|
|
|
|
{
|
|
|
|
unsigned long *p;
|
|
|
|
int l;
|
|
|
|
if (!v)
|
|
|
|
return 1;
|
|
|
|
l = n[1];
|
|
|
|
p = n + 2;
|
|
|
|
while (l) {
|
|
|
|
int i = l/2;
|
|
|
|
unsigned long *q = p + 2 * i;
|
|
|
|
if (*q == v) {
|
|
|
|
q[1]++;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (*q > v) {
|
|
|
|
l = i;
|
|
|
|
} else {
|
|
|
|
p = q + 2;
|
|
|
|
l -= i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (++n[1] == n[0])
|
|
|
|
return 0;
|
|
|
|
memmove(p + 2, p, n[1] * 2 * sizeof(unsigned long) - ((void *)p - (void *)n));
|
|
|
|
p[0] = v;
|
|
|
|
p[1] = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s)
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
int i;
|
|
|
|
if (n[0] == n[1])
|
|
|
|
return;
|
2012-06-13 15:24:57 +00:00
|
|
|
for (i = 0, p = s->s_mem; i < c->num; i++, p += c->size) {
|
2006-03-25 11:06:39 +00:00
|
|
|
if (slab_bufctl(s)[i] != BUFCTL_ACTIVE)
|
|
|
|
continue;
|
|
|
|
if (!add_caller(n, (unsigned long)*dbg_userword(c, p)))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_symbol(struct seq_file *m, unsigned long address)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_KALLSYMS
|
|
|
|
unsigned long offset, size;
|
2007-07-17 11:03:51 +00:00
|
|
|
char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
|
2006-03-25 11:06:39 +00:00
|
|
|
|
2007-05-08 07:28:47 +00:00
|
|
|
if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
|
2006-03-25 11:06:39 +00:00
|
|
|
seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
|
2007-05-08 07:28:47 +00:00
|
|
|
if (modname[0])
|
2006-03-25 11:06:39 +00:00
|
|
|
seq_printf(m, " [%s]", modname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
seq_printf(m, "%p", (void *)address);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int leaks_show(struct seq_file *m, void *p)
|
|
|
|
{
|
2012-06-22 17:42:49 +00:00
|
|
|
struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
|
2006-03-25 11:06:39 +00:00
|
|
|
struct slab *slabp;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
const char *name;
|
|
|
|
unsigned long *n = m->private;
|
|
|
|
int node;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!(cachep->flags & SLAB_STORE_USER))
|
|
|
|
return 0;
|
|
|
|
if (!(cachep->flags & SLAB_RED_ZONE))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* OK, we can do it */
|
|
|
|
|
|
|
|
n[1] = 0;
|
|
|
|
|
|
|
|
for_each_online_node(node) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
check_irq_on();
|
|
|
|
spin_lock_irq(&l3->list_lock);
|
|
|
|
|
2006-06-23 09:03:17 +00:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list)
|
2006-03-25 11:06:39 +00:00
|
|
|
handle_slab(n, cachep, slabp);
|
2006-06-23 09:03:17 +00:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list)
|
2006-03-25 11:06:39 +00:00
|
|
|
handle_slab(n, cachep, slabp);
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
}
|
|
|
|
name = cachep->name;
|
|
|
|
if (n[0] == n[1]) {
|
|
|
|
/* Increase the buffer size */
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_unlock(&slab_mutex);
|
2006-03-25 11:06:39 +00:00
|
|
|
m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
|
|
|
|
if (!m->private) {
|
|
|
|
/* Too bad, we are really out */
|
|
|
|
m->private = n;
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2006-03-25 11:06:39 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
*(unsigned long *)m->private = n[0] * 2;
|
|
|
|
kfree(n);
|
2012-07-06 20:25:12 +00:00
|
|
|
mutex_lock(&slab_mutex);
|
2006-03-25 11:06:39 +00:00
|
|
|
/* Now make sure this entry will be retried */
|
|
|
|
m->count = m->size;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (i = 0; i < n[1]; i++) {
|
|
|
|
seq_printf(m, "%s: %lu ", name, n[2*i+3]);
|
|
|
|
show_symbol(m, n[2*i+2]);
|
|
|
|
seq_putc(m, '\n');
|
|
|
|
}
|
2006-09-26 06:31:47 +00:00
|
|
|
|
2006-03-25 11:06:39 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-19 14:20:25 +00:00
|
|
|
static void *s_next(struct seq_file *m, void *p, loff_t *pos)
|
|
|
|
{
|
|
|
|
return seq_list_next(p, &slab_caches, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void s_stop(struct seq_file *m, void *p)
|
|
|
|
{
|
|
|
|
mutex_unlock(&slab_mutex);
|
|
|
|
}
|
|
|
|
|
2008-10-05 20:59:10 +00:00
|
|
|
static const struct seq_operations slabstats_op = {
|
2006-03-25 11:06:39 +00:00
|
|
|
.start = leaks_start,
|
|
|
|
.next = s_next,
|
|
|
|
.stop = s_stop,
|
|
|
|
.show = leaks_show,
|
|
|
|
};
|
2008-10-05 20:59:10 +00:00
|
|
|
|
|
|
|
static int slabstats_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
|
|
|
int ret = -ENOMEM;
|
|
|
|
if (n) {
|
|
|
|
ret = seq_open(file, &slabstats_op);
|
|
|
|
if (!ret) {
|
|
|
|
struct seq_file *m = file->private_data;
|
|
|
|
*n = PAGE_SIZE / (2 * sizeof(unsigned long));
|
|
|
|
m->private = n;
|
|
|
|
n = NULL;
|
|
|
|
}
|
|
|
|
kfree(n);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations proc_slabstats_operations = {
|
|
|
|
.open = slabstats_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = seq_release_private,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int __init slab_proc_init(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
|
2006-03-25 11:06:39 +00:00
|
|
|
#endif
|
2008-10-05 20:59:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
module_init(slab_proc_init);
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
|
|
|
|
2005-09-03 22:55:07 +00:00
|
|
|
/**
|
|
|
|
* ksize - get the actual amount of memory allocated for a given object
|
|
|
|
* @objp: Pointer to the object
|
|
|
|
*
|
|
|
|
* kmalloc may internally round up allocations and return more memory
|
|
|
|
* than requested. ksize() can be used to determine the actual amount of
|
|
|
|
* memory allocated. The caller may use this additional memory, even though
|
|
|
|
* a smaller amount of memory was initially specified with the kmalloc call.
|
|
|
|
* The caller must guarantee that objp points to a valid object previously
|
|
|
|
* allocated with either kmalloc() or kmem_cache_alloc(). The object
|
|
|
|
* must not be freed during the duration of the call.
|
|
|
|
*/
|
2007-05-06 21:48:40 +00:00
|
|
|
size_t ksize(const void *objp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-10-16 08:24:46 +00:00
|
|
|
BUG_ON(!objp);
|
|
|
|
if (unlikely(objp == ZERO_SIZE_PTR))
|
2005-09-03 22:55:07 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-06-13 15:24:58 +00:00
|
|
|
return virt_to_cache(objp)->object_size;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-02-10 13:21:44 +00:00
|
|
|
EXPORT_SYMBOL(ksize);
|