2005-04-17 06:20:36 +08: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-20 07:27:18 +08:00
|
|
|
* slabs and you must pass objects with the same initializations to
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
* The c_cpuarray may not be read with enabled local interrupts -
|
2005-04-17 06:20:36 +08:00
|
|
|
* it's changed with a smp_call_function().
|
|
|
|
*
|
|
|
|
* SMP synchronization:
|
|
|
|
* constructors and destructors are called without any locking.
|
2006-02-01 19:05:50 +08:00
|
|
|
* Several members in struct kmem_cache and struct slab never change, they
|
2005-04-17 06:20:36 +08: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
|
2006-01-19 09:42:33 +08:00
|
|
|
* The global cache-chain is protected by the mutex 'cache_chain_mutex'.
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08: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-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/mm.h>
|
2006-06-27 17:53:52 +08:00
|
|
|
#include <linux/poison.h>
|
2005-04-17 06:20:36 +08: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 19:16:07 +08:00
|
|
|
#include <linux/cpuset.h>
|
2008-10-06 04:59:10 +08:00
|
|
|
#include <linux/proc_fs.h>
|
2005-04-17 06:20:36 +08: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 15:09:02 +08:00
|
|
|
#include <linux/string.h>
|
2006-12-07 12:36:41 +08:00
|
|
|
#include <linux/uaccess.h>
|
2005-09-10 04:03:32 +08:00
|
|
|
#include <linux/nodemask.h>
|
2009-06-11 20:22:40 +08:00
|
|
|
#include <linux/kmemleak.h>
|
2006-01-19 09:42:36 +08:00
|
|
|
#include <linux/mempolicy.h>
|
2006-01-19 09:42:33 +08:00
|
|
|
#include <linux/mutex.h>
|
2006-12-08 18:39:44 +08:00
|
|
|
#include <linux/fault-inject.h>
|
2006-06-27 17:54:55 +08:00
|
|
|
#include <linux/rtmutex.h>
|
2006-12-13 16:34:27 +08:00
|
|
|
#include <linux/reciprocal_div.h>
|
2008-04-30 15:55:01 +08:00
|
|
|
#include <linux/debugobjects.h>
|
2008-05-10 02:35:53 +08:00
|
|
|
#include <linux/kmemcheck.h>
|
2010-03-28 10:40:47 +08:00
|
|
|
#include <linux/memory.h>
|
2011-05-21 03:50:29 +08:00
|
|
|
#include <linux/prefetch.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
|
|
|
|
/*
|
2007-05-07 05:50:16 +08:00
|
|
|
* DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
|
2005-04-17 06:20:36 +08: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 09:26:44 +08:00
|
|
|
#define REDZONE_ALIGN max(BYTES_PER_WORD, __alignof__(unsigned long long))
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#ifndef ARCH_KMALLOC_FLAGS
|
|
|
|
#define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Legal flag mask for kmem_cache_create(). */
|
|
|
|
#if DEBUG
|
2007-05-07 05:50:16 +08:00
|
|
|
# define CREATE_MASK (SLAB_RED_ZONE | \
|
2005-04-17 06:20:36 +08:00
|
|
|
SLAB_POISON | SLAB_HWCACHE_ALIGN | \
|
2006-03-22 16:08:15 +08:00
|
|
|
SLAB_CACHE_DMA | \
|
2007-05-07 05:49:56 +08:00
|
|
|
SLAB_STORE_USER | \
|
2005-04-17 06:20:36 +08:00
|
|
|
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
|
2008-04-30 15:55:01 +08:00
|
|
|
SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
|
2008-05-10 02:35:53 +08:00
|
|
|
SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK)
|
2005-04-17 06:20:36 +08:00
|
|
|
#else
|
2006-03-22 16:08:15 +08:00
|
|
|
# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \
|
2007-05-07 05:49:56 +08:00
|
|
|
SLAB_CACHE_DMA | \
|
2005-04-17 06:20:36 +08:00
|
|
|
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
|
2008-04-30 15:55:01 +08:00
|
|
|
SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
|
2008-05-10 02:35:53 +08:00
|
|
|
SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK)
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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-04 06:55:03 +08:00
|
|
|
typedef unsigned int kmem_bufctl_t;
|
2005-04-17 06:20:36 +08:00
|
|
|
#define BUFCTL_END (((kmem_bufctl_t)(~0U))-0)
|
|
|
|
#define BUFCTL_FREE (((kmem_bufctl_t)(~0U))-1)
|
2006-03-25 19:06:39 +08:00
|
|
|
#define BUFCTL_ACTIVE (((kmem_bufctl_t)(~0U))-2)
|
|
|
|
#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-3)
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
struct rcu_head head;
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep;
|
2006-01-08 17:00:37 +08:00
|
|
|
void *addr;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2011-03-10 15:22:24 +08: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-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
spinlock_t lock;
|
2007-10-17 14:30:05 +08:00
|
|
|
void *entry[]; /*
|
2006-03-22 16:08:11 +08:00
|
|
|
* Must have this definition in here for the proper
|
|
|
|
* alignment of array_cache. Also simplifies accessing
|
|
|
|
* the entries.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* bootstrap: The caches do not work without cpuarrays anymore, but the
|
|
|
|
* cpuarrays are allocated from the generic caches...
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
#define BOOT_CPUCACHE_ENTRIES 1
|
|
|
|
struct arraycache_init {
|
|
|
|
struct array_cache cache;
|
2006-01-08 17:00:37 +08:00
|
|
|
void *entries[BOOT_CPUCACHE_ENTRIES];
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2005-09-10 04:03:32 +08:00
|
|
|
* The slab lists for all objects.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
struct kmem_list3 {
|
2006-01-08 17:00:37 +08: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 15:27:56 +08:00
|
|
|
unsigned int colour_next; /* Per-node cache coloring */
|
2006-01-08 17:00:37 +08:00
|
|
|
spinlock_t list_lock;
|
|
|
|
struct array_cache *shared; /* shared per node */
|
|
|
|
struct array_cache **alien; /* on other nodes */
|
2006-03-22 16:09:05 +08:00
|
|
|
unsigned long next_reap; /* updated without locking */
|
|
|
|
int free_touched; /* updated without locking */
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
|
|
|
* Need this for bootstrapping a per node allocator.
|
|
|
|
*/
|
2008-01-25 14:20:51 +08:00
|
|
|
#define NUM_INIT_LISTS (3 * MAX_NUMNODES)
|
2011-01-12 07:49:32 +08:00
|
|
|
static struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
|
2005-09-10 04:03:32 +08:00
|
|
|
#define CACHE_CACHE 0
|
2008-01-25 14:20:51 +08:00
|
|
|
#define SIZE_AC MAX_NUMNODES
|
|
|
|
#define SIZE_L3 (2 * MAX_NUMNODES)
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-06-30 16:55:45 +08: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-11 00:40:04 +08:00
|
|
|
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp);
|
2006-11-22 22:55:48 +08:00
|
|
|
static void cache_reap(struct work_struct *unused);
|
2006-06-30 16:55:45 +08:00
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
2006-03-22 16:08:11 +08: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-10 04:03:32 +08:00
|
|
|
*/
|
2005-09-23 12:43:58 +08:00
|
|
|
static __always_inline int index_of(const size_t size)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
2006-02-01 19:05:44 +08:00
|
|
|
extern void __bad_size(void);
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
if (__builtin_constant_p(size)) {
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
#define CACHE(x) \
|
|
|
|
if (size <=x) \
|
|
|
|
return i; \
|
|
|
|
else \
|
|
|
|
i++;
|
2008-03-06 05:58:17 +08:00
|
|
|
#include <linux/kmalloc_sizes.h>
|
2005-09-10 04:03:32 +08:00
|
|
|
#undef CACHE
|
2006-02-01 19:05:44 +08:00
|
|
|
__bad_size();
|
2005-09-23 12:43:58 +08:00
|
|
|
} else
|
2006-02-01 19:05:44 +08:00
|
|
|
__bad_size();
|
2005-09-10 04:03:32 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-06-23 17:03:46 +08:00
|
|
|
static int slab_early_init = 1;
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
#define INDEX_AC index_of(sizeof(struct arraycache_init))
|
|
|
|
#define INDEX_L3 index_of(sizeof(struct kmem_list3))
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:48 +08:00
|
|
|
static void kmem_list3_init(struct kmem_list3 *parent)
|
2005-09-10 04:03:32 +08: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 15:27:56 +08:00
|
|
|
parent->colour_next = 0;
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_lock_init(&parent->list_lock);
|
|
|
|
parent->free_objects = 0;
|
|
|
|
parent->free_touched = 0;
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
#define MAKE_LIST(cachep, listp, slab, nodeid) \
|
|
|
|
do { \
|
|
|
|
INIT_LIST_HEAD(listp); \
|
|
|
|
list_splice(&(cachep->nodelists[nodeid]->slab), listp); \
|
2005-09-10 04:03:32 +08:00
|
|
|
} while (0)
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
#define MAKE_ALL_LISTS(cachep, ptr, nodeid) \
|
|
|
|
do { \
|
2005-09-10 04:03:32 +08: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-17 06:20:36 +08:00
|
|
|
|
|
|
|
#define CFLGS_OFF_SLAB (0x80000000UL)
|
|
|
|
#define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB)
|
|
|
|
|
|
|
|
#define BATCHREFILL_LIMIT 16
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Optimization question: fewer reaps means less probability for unnessary
|
|
|
|
* cpucache drain/refill cycles.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
2005-11-08 23:44:08 +08:00
|
|
|
* OTOH the cpuarrays can contain lots of objects,
|
2005-04-17 06:20:36 +08: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 16:55:45 +08:00
|
|
|
#define STATS_ADD_REAPED(x,y) ((x)->reaped += (y))
|
2006-03-22 16:08:11 +08:00
|
|
|
#define STATS_SET_HIGH(x) \
|
|
|
|
do { \
|
|
|
|
if ((x)->num_active > (x)->high_mark) \
|
|
|
|
(x)->high_mark = (x)->num_active; \
|
|
|
|
} while (0)
|
2005-04-17 06:20:36 +08:00
|
|
|
#define STATS_INC_ERR(x) ((x)->errors++)
|
|
|
|
#define STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
|
2005-09-10 04:03:32 +08:00
|
|
|
#define STATS_INC_NODEFREES(x) ((x)->node_frees++)
|
2006-04-11 13:52:54 +08:00
|
|
|
#define STATS_INC_ACOVERFLOW(x) ((x)->node_overflow++)
|
2006-03-22 16:08:11 +08:00
|
|
|
#define STATS_SET_FREEABLE(x, i) \
|
|
|
|
do { \
|
|
|
|
if ((x)->max_freeable < i) \
|
|
|
|
(x)->max_freeable = i; \
|
|
|
|
} while (0)
|
2005-04-17 06:20:36 +08: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 08:19:03 +08:00
|
|
|
#define STATS_ADD_REAPED(x,y) do { (void)(y); } while (0)
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
#define STATS_INC_NODEFREES(x) do { } while (0)
|
2006-04-11 13:52:54 +08:00
|
|
|
#define STATS_INC_ACOVERFLOW(x) do { } while (0)
|
2006-03-22 16:08:11 +08:00
|
|
|
#define STATS_SET_FREEABLE(x, i) do { } while (0)
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* memory layout of objects:
|
2005-04-17 06:20:36 +08:00
|
|
|
* 0 : objp
|
2006-02-01 19:05:42 +08:00
|
|
|
* 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that
|
2005-04-17 06:20:36 +08: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 19:05:42 +08:00
|
|
|
* cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1:
|
2005-04-17 06:20:36 +08:00
|
|
|
* redzone word.
|
2006-02-01 19:05:42 +08:00
|
|
|
* cachep->obj_offset: The real object.
|
|
|
|
* cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
|
2006-03-22 16:08:11 +08:00
|
|
|
* cachep->buffer_size - 1* BYTES_PER_WORD: last caller address
|
|
|
|
* [BYTES_PER_WORD long]
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2006-02-01 19:05:50 +08:00
|
|
|
static int obj_offset(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:42 +08:00
|
|
|
return cachep->obj_offset;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static int obj_size(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:42 +08:00
|
|
|
return cachep->obj_size;
|
2005-04-17 06:20:36 +08: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 15:22:59 +08:00
|
|
|
static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp)
|
2005-04-17 06:20:36 +08: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 15:22:59 +08:00
|
|
|
return (unsigned long long*) (objp + obj_offset(cachep) -
|
|
|
|
sizeof(unsigned long long));
|
2005-04-17 06:20:36 +08: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 15:22:59 +08:00
|
|
|
static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
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 15:22:59 +08:00
|
|
|
return (unsigned long long *)(objp + cachep->buffer_size -
|
|
|
|
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 09:26:44 +08:00
|
|
|
REDZONE_ALIGN);
|
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 15:22:59 +08:00
|
|
|
return (unsigned long long *) (objp + cachep->buffer_size -
|
|
|
|
sizeof(unsigned long long));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void **dbg_userword(struct kmem_cache *cachep, void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
BUG_ON(!(cachep->flags & SLAB_STORE_USER));
|
2006-02-01 19:05:42 +08:00
|
|
|
return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2006-02-01 19:05:42 +08:00
|
|
|
#define obj_offset(x) 0
|
|
|
|
#define obj_size(cachep) (cachep->buffer_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 15:22:59 +08:00
|
|
|
#define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;})
|
|
|
|
#define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;})
|
2005-04-17 06:20:36 +08:00
|
|
|
#define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;})
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2009-12-11 15:45:30 +08:00
|
|
|
#ifdef CONFIG_TRACING
|
2008-08-11 01:14:05 +08:00
|
|
|
size_t slab_buffer_size(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
return cachep->buffer_size;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(slab_buffer_size);
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Do not go above this order unless 0 objects fit into the slab.
|
|
|
|
*/
|
|
|
|
#define BREAK_GFP_ORDER_HI 1
|
|
|
|
#define BREAK_GFP_ORDER_LO 0
|
|
|
|
static int slab_break_gfp_order = BREAK_GFP_ORDER_LO;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Functions for storing/retrieving the cachep and or slab from the page
|
|
|
|
* allocator. These are used to find the slab an obj belongs to. With kfree(),
|
|
|
|
* these are used to find the cache which an obj belongs to.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2005-11-14 08:06:46 +08:00
|
|
|
static inline void page_set_cache(struct page *page, struct kmem_cache *cache)
|
|
|
|
{
|
|
|
|
page->lru.next = (struct list_head *)cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct kmem_cache *page_get_cache(struct page *page)
|
|
|
|
{
|
2007-05-07 05:49:39 +08:00
|
|
|
page = compound_head(page);
|
2006-06-23 17:03:40 +08:00
|
|
|
BUG_ON(!PageSlab(page));
|
2005-11-14 08:06:46 +08:00
|
|
|
return (struct kmem_cache *)page->lru.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void page_set_slab(struct page *page, struct slab *slab)
|
|
|
|
{
|
|
|
|
page->lru.prev = (struct list_head *)slab;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct slab *page_get_slab(struct page *page)
|
|
|
|
{
|
2006-06-23 17:03:40 +08:00
|
|
|
BUG_ON(!PageSlab(page));
|
2005-11-14 08:06:46 +08:00
|
|
|
return (struct slab *)page->lru.prev;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
static inline struct kmem_cache *virt_to_cache(const void *obj)
|
|
|
|
{
|
2007-05-07 05:49:41 +08:00
|
|
|
struct page *page = virt_to_head_page(obj);
|
2006-02-01 19:05:49 +08:00
|
|
|
return page_get_cache(page);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct slab *virt_to_slab(const void *obj)
|
|
|
|
{
|
2007-05-07 05:49:41 +08:00
|
|
|
struct page *page = virt_to_head_page(obj);
|
2006-02-01 19:05:49 +08:00
|
|
|
return page_get_slab(page);
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:10 +08:00
|
|
|
static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab,
|
|
|
|
unsigned int idx)
|
|
|
|
{
|
|
|
|
return slab->s_mem + cache->buffer_size * idx;
|
|
|
|
}
|
|
|
|
|
2006-12-13 16:34:27 +08:00
|
|
|
/*
|
|
|
|
* We want to avoid an expensive divide : (offset / cache->buffer_size)
|
|
|
|
* Using the fact that buffer_size is a constant for a particular cache,
|
|
|
|
* we can replace (offset / cache->buffer_size) by
|
|
|
|
* 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 16:08:10 +08:00
|
|
|
{
|
2006-12-13 16:34:27 +08:00
|
|
|
u32 offset = (obj - slab->s_mem);
|
|
|
|
return reciprocal_divide(offset, cache->reciprocal_buffer_size);
|
2006-03-22 16:08:10 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* These are the default caches for kmalloc. Custom caches can have other sizes.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
{NULL,}
|
2005-04-17 06:20:36 +08:00
|
|
|
#undef CACHE
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct arraycache_init initarray_cache __initdata =
|
2006-01-08 17:00:37 +08:00
|
|
|
{ {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
|
2005-04-17 06:20:36 +08:00
|
|
|
static struct arraycache_init initarray_generic =
|
2006-01-08 17:00:37 +08:00
|
|
|
{ {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* internal cache of cache description objs */
|
2011-07-21 01:04:23 +08:00
|
|
|
static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES];
|
2006-02-01 19:05:50 +08:00
|
|
|
static struct kmem_cache cache_cache = {
|
2011-07-21 01:04:23 +08:00
|
|
|
.nodelists = cache_cache_nodelists,
|
2006-01-08 17:00:37 +08:00
|
|
|
.batchcount = 1,
|
|
|
|
.limit = BOOT_CPUCACHE_ENTRIES,
|
|
|
|
.shared = 1,
|
2006-02-01 19:05:50 +08:00
|
|
|
.buffer_size = sizeof(struct kmem_cache),
|
2006-01-08 17:00:37 +08:00
|
|
|
.name = "kmem_cache",
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2006-09-26 14:31:38 +08:00
|
|
|
#define BAD_ALIEN_MAGIC 0x01020304ul
|
|
|
|
|
2009-11-24 04:01:15 +08:00
|
|
|
/*
|
|
|
|
* chicken and egg problem: delay the per-cpu array allocation
|
|
|
|
* until the general caches are up.
|
|
|
|
*/
|
|
|
|
static enum {
|
|
|
|
NONE,
|
|
|
|
PARTIAL_AC,
|
|
|
|
PARTIAL_L3,
|
|
|
|
EARLY,
|
2011-11-29 04:12:40 +08:00
|
|
|
LATE,
|
2009-11-24 04:01:15 +08:00
|
|
|
FULL
|
|
|
|
} g_cpucache_up;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* used by boot code to determine if it can use slab based allocator
|
|
|
|
*/
|
|
|
|
int slab_is_available(void)
|
|
|
|
{
|
|
|
|
return g_cpucache_up >= EARLY;
|
|
|
|
}
|
|
|
|
|
2006-07-13 20:46:03 +08: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 14:31:38 +08: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 20:46:03 +08:00
|
|
|
*/
|
2006-09-26 14:31:38 +08:00
|
|
|
static struct lock_class_key on_slab_l3_key;
|
|
|
|
static struct lock_class_key on_slab_alc_key;
|
|
|
|
|
2011-07-22 21:26:05 +08: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-24 04:01:15 +08:00
|
|
|
static void init_node_lock_keys(int q)
|
2006-07-13 20:46:03 +08:00
|
|
|
{
|
2006-09-26 14:31:38 +08:00
|
|
|
struct cache_sizes *s = malloc_sizes;
|
|
|
|
|
2011-11-29 04:12:40 +08:00
|
|
|
if (g_cpucache_up < LATE)
|
2009-11-24 04:01:15 +08: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 20:33:14 +08:00
|
|
|
continue;
|
2011-07-22 21:26:05 +08:00
|
|
|
|
|
|
|
slab_set_lock_classes(s->cs_cachep, &on_slab_l3_key,
|
|
|
|
&on_slab_alc_key, q);
|
2006-07-13 20:46:03 +08:00
|
|
|
}
|
|
|
|
}
|
2009-11-24 04:01:15 +08:00
|
|
|
|
|
|
|
static inline void init_lock_keys(void)
|
|
|
|
{
|
|
|
|
int node;
|
|
|
|
|
|
|
|
for_each_node(node)
|
|
|
|
init_node_lock_keys(node);
|
|
|
|
}
|
2006-07-13 20:46:03 +08:00
|
|
|
#else
|
2009-11-24 04:01:15 +08:00
|
|
|
static void init_node_lock_keys(int q)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-09-26 14:31:38 +08:00
|
|
|
static inline void init_lock_keys(void)
|
2006-07-13 20:46:03 +08:00
|
|
|
{
|
|
|
|
}
|
2011-07-22 21:26:05 +08: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 20:46:03 +08:00
|
|
|
#endif
|
|
|
|
|
[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 12:32:14 +08:00
|
|
|
/*
|
2008-01-26 04:08:02 +08:00
|
|
|
* Guard access to the cache-chain.
|
[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 12:32:14 +08:00
|
|
|
*/
|
2006-01-19 09:42:33 +08:00
|
|
|
static DEFINE_MUTEX(cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
static struct list_head cache_chain;
|
|
|
|
|
2009-10-29 21:34:13 +08:00
|
|
|
static DEFINE_PER_CPU(struct delayed_work, slab_reap_work);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
return cachep->array[smp_processor_id()];
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
static inline struct kmem_cache *__find_general_cachep(size_t size,
|
|
|
|
gfp_t gfpflags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct cache_sizes *csizep = malloc_sizes;
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
/* This happens if someone tries to call
|
2006-01-08 17:00:37 +08: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-15 03:17:53 +08:00
|
|
|
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
2007-07-17 19:03:22 +08:00
|
|
|
if (!size)
|
|
|
|
return ZERO_SIZE_PTR;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
while (size > csizep->cs_size)
|
|
|
|
csizep++;
|
|
|
|
|
|
|
|
/*
|
2005-09-04 06:54:54 +08:00
|
|
|
* Really subtle: The last entry with cs->cs_size==ULONG_MAX
|
2005-04-17 06:20:36 +08:00
|
|
|
* has cs_{dma,}cachep==NULL. Thus no special case
|
|
|
|
* for large kmalloc calls required.
|
|
|
|
*/
|
2007-02-10 17:43:10 +08:00
|
|
|
#ifdef CONFIG_ZONE_DMA
|
2005-04-17 06:20:36 +08:00
|
|
|
if (unlikely(gfpflags & GFP_DMA))
|
|
|
|
return csizep->cs_dmacachep;
|
2007-02-10 17:43:10 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
return csizep->cs_cachep;
|
|
|
|
}
|
|
|
|
|
2006-09-26 14:31:02 +08:00
|
|
|
static struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags)
|
2005-05-01 23:58:38 +08:00
|
|
|
{
|
|
|
|
return __find_general_cachep(size, gfpflags);
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:45 +08:00
|
|
|
static size_t slab_mgmt_size(size_t nr_objs, size_t align)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:45 +08:00
|
|
|
return ALIGN(sizeof(struct slab)+nr_objs*sizeof(kmem_bufctl_t), align);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Calculate the number of objects and left-over bytes for a given buffer size.
|
|
|
|
*/
|
2006-02-01 19:05:45 +08: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-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:45 +08: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-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2008-04-30 15:55:07 +08:00
|
|
|
#define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
static void __slab_error(const char *function, struct kmem_cache *cachep,
|
|
|
|
char *msg)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
|
2006-01-08 17:00:37 +08:00
|
|
|
function, cachep->name, msg);
|
2005-04-17 06:20:36 +08:00
|
|
|
dump_stack();
|
|
|
|
}
|
|
|
|
|
2006-12-07 12:32:16 +08: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);
|
|
|
|
|
2006-03-10 09:33:54 +08: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 21:34:13 +08:00
|
|
|
static DEFINE_PER_CPU(unsigned long, slab_reap_node);
|
2006-03-10 09:33:54 +08: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-27 05:45:03 +08:00
|
|
|
node = next_node(cpu_to_mem(cpu), node_online_map);
|
2006-03-10 09:33:54 +08:00
|
|
|
if (node == MAX_NUMNODES)
|
2006-03-22 16:09:11 +08:00
|
|
|
node = first_node(node_online_map);
|
2006-03-10 09:33:54 +08:00
|
|
|
|
2009-10-29 21:34:13 +08:00
|
|
|
per_cpu(slab_reap_node, cpu) = node;
|
2006-03-10 09:33:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void next_reap_node(void)
|
|
|
|
{
|
2010-12-08 23:22:55 +08:00
|
|
|
int node = __this_cpu_read(slab_reap_node);
|
2006-03-10 09:33:54 +08:00
|
|
|
|
|
|
|
node = next_node(node, node_online_map);
|
|
|
|
if (unlikely(node >= MAX_NUMNODES))
|
|
|
|
node = first_node(node_online_map);
|
2010-12-08 23:22:55 +08:00
|
|
|
__this_cpu_write(slab_reap_node, node);
|
2006-03-10 09:33:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define init_reap_node(cpu) do { } while (0)
|
|
|
|
#define next_reap_node(void) do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
2005-04-17 06:20:36 +08: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 14:38:20 +08:00
|
|
|
static void __cpuinit start_cpu_timer(int cpu)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2009-10-29 21:34:13 +08:00
|
|
|
struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu);
|
2005-04-17 06:20:36 +08: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 22:54:01 +08:00
|
|
|
if (keventd_up() && reap_work->work.func == NULL) {
|
2006-03-10 09:33:54 +08:00
|
|
|
init_reap_node(cpu);
|
2010-07-20 01:59:42 +08:00
|
|
|
INIT_DELAYED_WORK_DEFERRABLE(reap_work, cache_reap);
|
2006-12-10 18:21:28 +08:00
|
|
|
schedule_delayed_work_on(cpu, reap_work,
|
|
|
|
__round_jiffies_relative(HZ, cpu));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
static struct array_cache *alloc_arraycache(int node, int entries,
|
2009-06-11 00:40:04 +08:00
|
|
|
int batchcount, gfp_t gfp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
int memsize = sizeof(void *) * entries + sizeof(struct array_cache);
|
2005-04-17 06:20:36 +08:00
|
|
|
struct array_cache *nc = NULL;
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
nc = kmalloc_node(memsize, gfp, node);
|
2009-06-11 20:22:40 +08:00
|
|
|
/*
|
|
|
|
* The array_cache structures contain pointers to free object.
|
2011-03-31 09:57:33 +08:00
|
|
|
* However, when such objects are allocated or transferred to another
|
2009-06-11 20:22:40 +08: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-17 06:20:36 +08:00
|
|
|
if (nc) {
|
|
|
|
nc->avail = 0;
|
|
|
|
nc->limit = entries;
|
|
|
|
nc->batchcount = batchcount;
|
|
|
|
nc->touched = 0;
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_lock_init(&nc->lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
return nc;
|
|
|
|
}
|
|
|
|
|
2006-03-25 19:06:44 +08: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-27 05:22:23 +08:00
|
|
|
int nr = min3(from->avail, max, to->limit - to->avail);
|
2006-03-25 19:06:44 +08: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 16:50:08 +08:00
|
|
|
#ifndef CONFIG_NUMA
|
|
|
|
|
|
|
|
#define drain_alien_cache(cachep, alien) do { } while (0)
|
|
|
|
#define reap_alien(cachep, l3) do { } while (0)
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
static inline struct array_cache **alloc_alien_cache(int node, int limit, gfp_t gfp)
|
2006-09-27 16:50:08 +08: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 12:32:30 +08:00
|
|
|
static inline void *____cache_alloc_node(struct kmem_cache *cachep,
|
2006-09-27 16:50:08 +08:00
|
|
|
gfp_t flags, int nodeid)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* CONFIG_NUMA */
|
|
|
|
|
2006-12-07 12:32:30 +08:00
|
|
|
static void *____cache_alloc_node(struct kmem_cache *, gfp_t, int);
|
2006-03-24 19:16:08 +08:00
|
|
|
static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
|
2006-01-19 09:42:36 +08:00
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
static struct array_cache **alloc_alien_cache(int node, int limit, gfp_t gfp)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
struct array_cache **ac_ptr;
|
2007-02-21 05:57:52 +08:00
|
|
|
int memsize = sizeof(void *) * nr_node_ids;
|
2005-09-10 04:03:32 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (limit > 1)
|
|
|
|
limit = 12;
|
2010-01-06 15:25:23 +08:00
|
|
|
ac_ptr = kzalloc_node(memsize, gfp, node);
|
2005-09-10 04:03:32 +08:00
|
|
|
if (ac_ptr) {
|
|
|
|
for_each_node(i) {
|
2010-01-06 15:25:23 +08:00
|
|
|
if (i == node || !node_online(i))
|
2005-09-10 04:03:32 +08:00
|
|
|
continue;
|
2009-06-11 00:40:04 +08:00
|
|
|
ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d, gfp);
|
2005-09-10 04:03:32 +08:00
|
|
|
if (!ac_ptr[i]) {
|
2007-11-15 08:58:35 +08:00
|
|
|
for (i--; i >= 0; i--)
|
2005-09-10 04:03:32 +08:00
|
|
|
kfree(ac_ptr[i]);
|
|
|
|
kfree(ac_ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ac_ptr;
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:48 +08:00
|
|
|
static void free_alien_cache(struct array_cache **ac_ptr)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!ac_ptr)
|
|
|
|
return;
|
|
|
|
for_each_node(i)
|
2006-01-08 17:00:37 +08:00
|
|
|
kfree(ac_ptr[i]);
|
2005-09-10 04:03:32 +08:00
|
|
|
kfree(ac_ptr);
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void __drain_alien_cache(struct kmem_cache *cachep,
|
2006-02-01 19:05:48 +08:00
|
|
|
struct array_cache *ac, int node)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
struct kmem_list3 *rl3 = cachep->nodelists[node];
|
|
|
|
|
|
|
|
if (ac->avail) {
|
|
|
|
spin_lock(&rl3->list_lock);
|
2006-03-25 19:06:45 +08: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 23:54:37 +08:00
|
|
|
if (rl3->shared)
|
|
|
|
transfer_objects(rl3->shared, ac, ac->limit);
|
2006-03-25 19:06:45 +08:00
|
|
|
|
2005-09-23 12:44:02 +08:00
|
|
|
free_block(cachep, ac->entry, ac->avail, node);
|
2005-09-10 04:03:32 +08:00
|
|
|
ac->avail = 0;
|
|
|
|
spin_unlock(&rl3->list_lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-10 09:33:54 +08: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 23:22:55 +08:00
|
|
|
int node = __this_cpu_read(slab_reap_node);
|
2006-03-10 09:33:54 +08:00
|
|
|
|
|
|
|
if (l3->alien) {
|
|
|
|
struct array_cache *ac = l3->alien[node];
|
2006-03-25 19:06:45 +08:00
|
|
|
|
|
|
|
if (ac && ac->avail && spin_trylock_irq(&ac->lock)) {
|
2006-03-10 09:33:54 +08:00
|
|
|
__drain_alien_cache(cachep, ac, node);
|
|
|
|
spin_unlock_irq(&ac->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
static void drain_alien_cache(struct kmem_cache *cachep,
|
|
|
|
struct array_cache **alien)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
int i = 0;
|
2005-09-10 04:03:32 +08: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 15:27:59 +08:00
|
|
|
ac = alien[i];
|
2005-09-10 04:03:32 +08:00
|
|
|
if (ac) {
|
|
|
|
spin_lock_irqsave(&ac->lock, flags);
|
|
|
|
__drain_alien_cache(cachep, ac, i);
|
|
|
|
spin_unlock_irqrestore(&ac->lock, flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-06-23 17:03:05 +08:00
|
|
|
|
2006-07-13 20:44:38 +08:00
|
|
|
static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
|
2006-06-23 17:03:05 +08:00
|
|
|
{
|
|
|
|
struct slab *slabp = virt_to_slab(objp);
|
|
|
|
int nodeid = slabp->nodeid;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
struct array_cache *alien = NULL;
|
2006-10-06 15:43:52 +08: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-27 05:45:03 +08:00
|
|
|
node = numa_mem_id();
|
2006-06-23 17:03:05 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure we are not freeing a object from another node to the array
|
|
|
|
* cache on this cpu.
|
|
|
|
*/
|
2007-05-03 01:27:18 +08:00
|
|
|
if (likely(slabp->nodeid == node))
|
2006-06-23 17:03:05 +08:00
|
|
|
return 0;
|
|
|
|
|
2006-10-06 15:43:52 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-06-23 17:03:05 +08:00
|
|
|
STATS_INC_NODEFREES(cachep);
|
|
|
|
if (l3->alien && l3->alien[nodeid]) {
|
|
|
|
alien = l3->alien[nodeid];
|
2006-07-13 20:44:38 +08:00
|
|
|
spin_lock(&alien->lock);
|
2006-06-23 17:03:05 +08:00
|
|
|
if (unlikely(alien->avail == alien->limit)) {
|
|
|
|
STATS_INC_ACOVERFLOW(cachep);
|
|
|
|
__drain_alien_cache(cachep, alien, nodeid);
|
|
|
|
}
|
|
|
|
alien->entry[alien->avail++] = objp;
|
|
|
|
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-10 04:03:32 +08:00
|
|
|
#endif
|
|
|
|
|
2010-03-28 10:40:47 +08: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.
|
|
|
|
*
|
|
|
|
* Must hold cache_chain_mutex.
|
|
|
|
*/
|
|
|
|
static int init_cache_nodelists_node(int node)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
const int memsize = sizeof(struct kmem_list3);
|
|
|
|
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* go. cache_chain_mutex is sufficient
|
|
|
|
* 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 18:05:09 +08: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-27 05:45:03 +08:00
|
|
|
int node = cpu_to_mem(cpu);
|
2009-03-13 12:19:46 +08:00
|
|
|
const struct cpumask *mask = cpumask_of_node(node);
|
2007-10-18 18:05:09 +08:00
|
|
|
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
|
|
|
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-18 01:43:12 +08:00
|
|
|
if (!cpumask_empty(mask)) {
|
2007-10-18 18:05:09 +08: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.
|
|
|
|
*/
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
drain_freelist(cachep, l3, l3->free_objects);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __cpuinit cpuup_prepare(long cpu)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep;
|
2005-09-10 04:03:32 +08: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-27 05:45:03 +08:00
|
|
|
int node = cpu_to_mem(cpu);
|
2010-03-28 10:40:47 +08:00
|
|
|
int err;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-10-18 18:05:09 +08: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 10:40:47 +08:00
|
|
|
err = init_cache_nodelists_node(node);
|
|
|
|
if (err < 0)
|
|
|
|
goto bad;
|
2007-10-18 18:05:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we can go ahead with allocating the shared arrays and
|
|
|
|
* array caches
|
|
|
|
*/
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
|
|
|
struct array_cache *nc;
|
|
|
|
struct array_cache *shared = NULL;
|
|
|
|
struct array_cache **alien = NULL;
|
|
|
|
|
|
|
|
nc = alloc_arraycache(node, cachep->limit,
|
2009-06-11 00:40:04 +08:00
|
|
|
cachep->batchcount, GFP_KERNEL);
|
2007-10-18 18:05:09 +08:00
|
|
|
if (!nc)
|
|
|
|
goto bad;
|
|
|
|
if (cachep->shared) {
|
|
|
|
shared = alloc_arraycache(node,
|
|
|
|
cachep->shared * cachep->batchcount,
|
2009-06-11 00:40:04 +08:00
|
|
|
0xbaadf00d, GFP_KERNEL);
|
2007-10-18 18:05:11 +08:00
|
|
|
if (!shared) {
|
|
|
|
kfree(nc);
|
2005-04-17 06:20:36 +08:00
|
|
|
goto bad;
|
2007-10-18 18:05:11 +08:00
|
|
|
}
|
2007-10-18 18:05:09 +08:00
|
|
|
}
|
|
|
|
if (use_alien_caches) {
|
2009-06-11 00:40:04 +08:00
|
|
|
alien = alloc_alien_cache(node, cachep->limit, GFP_KERNEL);
|
2007-10-18 18:05:11 +08:00
|
|
|
if (!alien) {
|
|
|
|
kfree(shared);
|
|
|
|
kfree(nc);
|
2007-10-18 18:05:09 +08:00
|
|
|
goto bad;
|
2007-10-18 18:05:11 +08:00
|
|
|
}
|
2007-10-18 18:05:09 +08: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 15:27:59 +08:00
|
|
|
#ifdef CONFIG_NUMA
|
2007-10-18 18:05:09 +08:00
|
|
|
if (!l3->alien) {
|
|
|
|
l3->alien = alien;
|
|
|
|
alien = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2007-10-18 18:05:09 +08:00
|
|
|
#endif
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
kfree(shared);
|
|
|
|
free_alien_cache(alien);
|
2011-07-22 21:26:05 +08:00
|
|
|
if (cachep->flags & SLAB_DEBUG_OBJECTS)
|
|
|
|
slab_set_debugobj_lock_classes_node(cachep, node);
|
2007-10-18 18:05:09 +08:00
|
|
|
}
|
2009-11-24 04:01:15 +08:00
|
|
|
init_node_lock_keys(node);
|
|
|
|
|
2007-10-18 18:05:09 +08:00
|
|
|
return 0;
|
|
|
|
bad:
|
2007-10-18 18:05:11 +08:00
|
|
|
cpuup_canceled(cpu);
|
2007-10-18 18:05:09 +08: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:
|
2008-01-26 04:08:02 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
2007-10-18 18:05:09 +08:00
|
|
|
err = cpuup_prepare(cpu);
|
2008-01-26 04:08:02 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case CPU_ONLINE:
|
2007-05-09 17:35:10 +08:00
|
|
|
case CPU_ONLINE_FROZEN:
|
2005-04-17 06:20:36 +08:00
|
|
|
start_cpu_timer(cpu);
|
|
|
|
break;
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
2007-05-09 17:34:22 +08:00
|
|
|
case CPU_DOWN_PREPARE:
|
2007-05-09 17:35:10 +08:00
|
|
|
case CPU_DOWN_PREPARE_FROZEN:
|
2007-05-09 17:34:22 +08:00
|
|
|
/*
|
|
|
|
* Shutdown cache reaper. Note that the cache_chain_mutex is
|
|
|
|
* 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 23:21:17 +08:00
|
|
|
cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu));
|
2007-05-09 17:34:22 +08:00
|
|
|
/* Now the cache_reaper is guaranteed to be not running. */
|
2009-10-29 21:34:13 +08:00
|
|
|
per_cpu(slab_reap_work, cpu).work.func = NULL;
|
2007-05-09 17:34:22 +08:00
|
|
|
break;
|
|
|
|
case CPU_DOWN_FAILED:
|
2007-05-09 17:35:10 +08:00
|
|
|
case CPU_DOWN_FAILED_FROZEN:
|
2007-05-09 17:34:22 +08:00
|
|
|
start_cpu_timer(cpu);
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_DEAD:
|
2007-05-09 17:35:10 +08: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 15:27:59 +08: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-20 07:27:18 +08: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 12:32:14 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_UP_CANCELED:
|
2007-05-09 17:35:10 +08:00
|
|
|
case CPU_UP_CANCELED_FROZEN:
|
2008-01-26 04:08:02 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
2007-10-18 18:05:09 +08:00
|
|
|
cpuup_canceled(cpu);
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-05-27 05:43:32 +08:00
|
|
|
return notifier_from_errno(err);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-06-27 17:54:09 +08:00
|
|
|
static struct notifier_block __cpuinitdata cpucache_notifier = {
|
|
|
|
&cpuup_callback, NULL, 0
|
|
|
|
};
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-03-28 10:40:47 +08: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.
|
|
|
|
*
|
|
|
|
* Must hold cache_chain_mutex.
|
|
|
|
*/
|
|
|
|
static int __meminit drain_cache_nodelists_node(int node)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
|
|
|
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:
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
ret = init_cache_nodelists_node(nid);
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
|
|
|
break;
|
|
|
|
case MEM_GOING_OFFLINE:
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
ret = drain_cache_nodelists_node(nid);
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
|
|
|
break;
|
|
|
|
case MEM_ONLINE:
|
|
|
|
case MEM_OFFLINE:
|
|
|
|
case MEM_CANCEL_ONLINE:
|
|
|
|
case MEM_CANCEL_OFFLINE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
out:
|
2011-03-23 07:30:49 +08:00
|
|
|
return notifier_from_errno(ret);
|
2010-03-28 10:40:47 +08:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_NUMA && CONFIG_MEMORY_HOTPLUG */
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
|
|
|
* swap the static kmem_list3 with kmalloced memory
|
|
|
|
*/
|
2010-03-28 10:40:47 +08:00
|
|
|
static void __init init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
|
|
|
|
int nodeid)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
struct kmem_list3 *ptr;
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_NOWAIT, nodeid);
|
2005-09-10 04:03:32 +08:00
|
|
|
BUG_ON(!ptr);
|
|
|
|
|
|
|
|
memcpy(ptr, list, sizeof(struct kmem_list3));
|
2006-07-03 15:25:28 +08:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->list_lock);
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
MAKE_ALL_LISTS(cachep, ptr, nodeid);
|
|
|
|
cachep->nodelists[nodeid] = ptr;
|
|
|
|
}
|
|
|
|
|
2008-01-25 14:20:51 +08: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Initialisation. Called after the page allocator have been initialised and
|
|
|
|
* before smp_init().
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
void __init kmem_cache_init(void)
|
|
|
|
{
|
|
|
|
size_t left_over;
|
|
|
|
struct cache_sizes *sizes;
|
|
|
|
struct cache_names *names;
|
2005-09-10 04:03:32 +08:00
|
|
|
int i;
|
2006-03-08 13:55:46 +08:00
|
|
|
int order;
|
2006-10-06 15:43:52 +08:00
|
|
|
int node;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2009-06-17 06:32:16 +08:00
|
|
|
if (num_possible_nodes() == 1)
|
2007-05-03 01:27:18 +08:00
|
|
|
use_alien_caches = 0;
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
for (i = 0; i < NUM_INIT_LISTS; i++) {
|
|
|
|
kmem_list3_init(&initkmem_list3[i]);
|
|
|
|
if (i < MAX_NUMNODES)
|
|
|
|
cache_cache.nodelists[i] = NULL;
|
|
|
|
}
|
2008-01-25 14:20:51 +08:00
|
|
|
set_up_list3s(&cache_cache, CACHE_CACHE);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Fragmentation resistance on low memory - only use bigger
|
|
|
|
* page orders on machines with more than 32MB of memory.
|
|
|
|
*/
|
2009-09-22 08:03:05 +08:00
|
|
|
if (totalram_pages > (32 << 20) >> PAGE_SHIFT)
|
2005-04-17 06:20:36 +08:00
|
|
|
slab_break_gfp_order = BREAK_GFP_ORDER_HI;
|
|
|
|
|
|
|
|
/* Bootstrap is tricky, because several objects are allocated
|
|
|
|
* from caches that do not exist yet:
|
2006-03-22 16:08:11 +08:00
|
|
|
* 1) initialize the cache_cache cache: it contains the struct
|
|
|
|
* kmem_cache structures of all caches, except cache_cache itself:
|
|
|
|
* cache_cache is statically allocated.
|
2005-09-10 04:03:32 +08: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-17 06:20:36 +08:00
|
|
|
* 2) Create the first kmalloc cache.
|
2006-02-01 19:05:50 +08:00
|
|
|
* The struct kmem_cache for the new cache is allocated normally.
|
2005-09-10 04:03:32 +08:00
|
|
|
* An __init data area is used for the head array.
|
|
|
|
* 3) Create the remaining kmalloc caches, with minimally sized
|
|
|
|
* head arrays.
|
2005-04-17 06:20:36 +08:00
|
|
|
* 4) Replace the __init data head arrays for cache_cache and the first
|
|
|
|
* kmalloc cache with kmalloc allocated arrays.
|
2005-09-10 04:03:32 +08:00
|
|
|
* 5) Replace the __init data for kmem_list3 for cache_cache and
|
|
|
|
* the other cache's with kmalloc allocated memory.
|
|
|
|
* 6) Resize the head arrays of the kmalloc caches to their final sizes.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
|
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-27 05:45:03 +08:00
|
|
|
node = numa_mem_id();
|
2006-10-06 15:43:52 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* 1) create the cache_cache */
|
|
|
|
INIT_LIST_HEAD(&cache_chain);
|
|
|
|
list_add(&cache_cache.next, &cache_chain);
|
|
|
|
cache_cache.colour_off = cache_line_size();
|
|
|
|
cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
|
2008-03-26 05:59:08 +08:00
|
|
|
cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-05-07 05:49:29 +08:00
|
|
|
/*
|
2011-07-21 01:04:23 +08:00
|
|
|
* struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
|
2007-05-07 05:49:29 +08:00
|
|
|
*/
|
2011-07-21 01:04:23 +08:00
|
|
|
cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
|
|
|
|
nr_node_ids * sizeof(struct kmem_list3 *);
|
2007-05-07 05:49:29 +08:00
|
|
|
#if DEBUG
|
|
|
|
cache_cache.obj_size = cache_cache.buffer_size;
|
|
|
|
#endif
|
2006-03-22 16:08:11 +08:00
|
|
|
cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
|
|
|
|
cache_line_size());
|
2006-12-13 16:34:27 +08:00
|
|
|
cache_cache.reciprocal_buffer_size =
|
|
|
|
reciprocal_value(cache_cache.buffer_size);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-08 13:55:46 +08:00
|
|
|
for (order = 0; order < MAX_ORDER; order++) {
|
|
|
|
cache_estimate(order, cache_cache.buffer_size,
|
|
|
|
cache_line_size(), 0, &left_over, &cache_cache.num);
|
|
|
|
if (cache_cache.num)
|
|
|
|
break;
|
|
|
|
}
|
2006-04-02 19:49:25 +08:00
|
|
|
BUG_ON(!cache_cache.num);
|
2006-03-08 13:55:46 +08:00
|
|
|
cache_cache.gfporder = order;
|
2006-01-08 17:00:37 +08:00
|
|
|
cache_cache.colour = left_over / cache_cache.colour_off;
|
|
|
|
cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
|
|
|
|
sizeof(struct slab), cache_line_size());
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* 2+3) create the kmalloc caches */
|
|
|
|
sizes = malloc_sizes;
|
|
|
|
names = cache_names;
|
|
|
|
|
2006-03-22 16:08:11 +08: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-10 04:03:32 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
|
2006-03-22 16:08:11 +08:00
|
|
|
sizes[INDEX_AC].cs_size,
|
|
|
|
ARCH_KMALLOC_MINALIGN,
|
|
|
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
2007-07-20 09:11:58 +08:00
|
|
|
NULL);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
if (INDEX_AC != INDEX_L3) {
|
2005-09-10 04:03:32 +08:00
|
|
|
sizes[INDEX_L3].cs_cachep =
|
2006-03-22 16:08:11 +08:00
|
|
|
kmem_cache_create(names[INDEX_L3].name,
|
|
|
|
sizes[INDEX_L3].cs_size,
|
|
|
|
ARCH_KMALLOC_MINALIGN,
|
|
|
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
2007-07-20 09:11:58 +08:00
|
|
|
NULL);
|
2006-03-22 16:08:11 +08:00
|
|
|
}
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-06-23 17:03:46 +08:00
|
|
|
slab_early_init = 0;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
while (sizes->cs_size != ULONG_MAX) {
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
|
|
|
* For performance, all the general caches are L1 aligned.
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
* allow tighter packing of the smaller caches.
|
|
|
|
*/
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!sizes->cs_cachep) {
|
2005-09-10 04:03:32 +08:00
|
|
|
sizes->cs_cachep = kmem_cache_create(names->name,
|
2006-03-22 16:08:11 +08:00
|
|
|
sizes->cs_size,
|
|
|
|
ARCH_KMALLOC_MINALIGN,
|
|
|
|
ARCH_KMALLOC_FLAGS|SLAB_PANIC,
|
2007-07-20 09:11:58 +08:00
|
|
|
NULL);
|
2006-03-22 16:08:11 +08:00
|
|
|
}
|
2007-02-10 17:43:10 +08:00
|
|
|
#ifdef CONFIG_ZONE_DMA
|
|
|
|
sizes->cs_dmacachep = kmem_cache_create(
|
|
|
|
names->name_dma,
|
2006-03-22 16:08:11 +08:00
|
|
|
sizes->cs_size,
|
|
|
|
ARCH_KMALLOC_MINALIGN,
|
|
|
|
ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
|
|
|
|
SLAB_PANIC,
|
2007-07-20 09:11:58 +08:00
|
|
|
NULL);
|
2007-02-10 17:43:10 +08:00
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
sizes++;
|
|
|
|
names++;
|
|
|
|
}
|
|
|
|
/* 4) Replace the bootstrap head arrays */
|
|
|
|
{
|
2006-07-03 15:25:28 +08:00
|
|
|
struct array_cache *ptr;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
|
|
|
|
memcpy(ptr, cpu_cache_get(&cache_cache),
|
2006-01-08 17:00:37 +08:00
|
|
|
sizeof(struct arraycache_init));
|
2006-07-03 15:25:28 +08:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->lock);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
cache_cache.array[smp_processor_id()] = ptr;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
|
2006-01-08 17:00:37 +08:00
|
|
|
!= &initarray_generic.cache);
|
2006-02-01 19:05:49 +08:00
|
|
|
memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
|
2006-01-08 17:00:37 +08:00
|
|
|
sizeof(struct arraycache_init));
|
2006-07-03 15:25:28 +08:00
|
|
|
/*
|
|
|
|
* Do not assume that spinlocks can be initialized via memcpy:
|
|
|
|
*/
|
|
|
|
spin_lock_init(&ptr->lock);
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
|
2006-01-08 17:00:37 +08:00
|
|
|
ptr;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2005-09-10 04:03:32 +08:00
|
|
|
/* 5) Replace the bootstrap kmem_list3's */
|
|
|
|
{
|
2006-10-06 15:43:52 +08:00
|
|
|
int nid;
|
|
|
|
|
2008-01-24 21:49:54 +08:00
|
|
|
for_each_online_node(nid) {
|
2008-03-26 05:59:08 +08:00
|
|
|
init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
|
2008-01-25 14:20:51 +08:00
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
init_list(malloc_sizes[INDEX_AC].cs_cachep,
|
2006-10-06 15:43:52 +08:00
|
|
|
&initkmem_list3[SIZE_AC + nid], nid);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
|
|
|
if (INDEX_AC != INDEX_L3) {
|
|
|
|
init_list(malloc_sizes[INDEX_L3].cs_cachep,
|
2006-10-06 15:43:52 +08:00
|
|
|
&initkmem_list3[SIZE_L3 + nid], nid);
|
2005-09-10 04:03:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-06-12 20:58:59 +08:00
|
|
|
g_cpucache_up = EARLY;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init kmem_cache_init_late(void)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cachep;
|
|
|
|
|
2011-11-29 04:12:40 +08:00
|
|
|
g_cpucache_up = LATE;
|
|
|
|
|
2011-07-29 05:22:56 +08:00
|
|
|
/* Annotate slab for lockdep -- annotate the malloc caches */
|
|
|
|
init_lock_keys();
|
|
|
|
|
2009-06-12 20:58:59 +08:00
|
|
|
/* 6) resize the head arrays to their final sizes */
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
list_for_each_entry(cachep, &cache_chain, next)
|
|
|
|
if (enable_cpucache(cachep, GFP_NOWAIT))
|
|
|
|
BUG();
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2006-09-26 14:31:38 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Done! */
|
|
|
|
g_cpucache_up = FULL;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Register a cpu startup notifier callback that initializes
|
|
|
|
* cpu_cache_get for all new cpus
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
register_cpu_notifier(&cpucache_notifier);
|
|
|
|
|
2010-03-28 10:40:47 +08: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 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* The reap timers are started later, with a module init call: That part
|
|
|
|
* of the kernel is not yet operational.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __init cpucache_init(void)
|
|
|
|
{
|
|
|
|
int cpu;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Register the timers that return unneeded pages to the page allocator
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2005-09-10 04:03:32 +08:00
|
|
|
for_each_online_cpu(cpu)
|
2006-03-22 16:08:11 +08:00
|
|
|
start_cpu_timer(cpu);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
__initcall(cpucache_init);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 19:05:50 +08:00
|
|
|
static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct page *page;
|
2006-06-23 17:03:17 +08:00
|
|
|
int nr_pages;
|
2005-04-17 06:20:36 +08:00
|
|
|
int i;
|
|
|
|
|
2006-04-11 13:52:56 +08:00
|
|
|
#ifndef CONFIG_MMU
|
2006-06-23 17:03:17 +08:00
|
|
|
/*
|
|
|
|
* Nommu uses slab's for process anonymous memory allocations, and thus
|
|
|
|
* requires __GFP_COMP to properly refcount higher order allocations
|
2006-04-11 13:52:56 +08:00
|
|
|
*/
|
2006-06-23 17:03:17 +08:00
|
|
|
flags |= __GFP_COMP;
|
2006-04-11 13:52:56 +08:00
|
|
|
#endif
|
2006-09-27 16:50:08 +08:00
|
|
|
|
2006-12-07 12:33:29 +08:00
|
|
|
flags |= cachep->gfpflags;
|
2007-10-16 16:25:52 +08:00
|
|
|
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
|
|
|
|
flags |= __GFP_RECLAIMABLE;
|
2006-06-23 17:03:17 +08:00
|
|
|
|
2009-06-17 10:50:13 +08:00
|
|
|
page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!page)
|
|
|
|
return NULL;
|
|
|
|
|
2006-06-23 17:03:17 +08:00
|
|
|
nr_pages = (1 << cachep->gfporder);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
|
2006-09-26 14:31:51 +08: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);
|
2006-06-23 17:03:17 +08:00
|
|
|
for (i = 0; i < nr_pages; i++)
|
|
|
|
__SetPageSlab(page + i);
|
2008-05-10 02:35:53 +08:00
|
|
|
|
2008-11-25 23:55:53 +08: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-10 02:35:53 +08:00
|
|
|
|
2006-06-23 17:03:17 +08:00
|
|
|
return page_address(page);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interface to system's page release.
|
|
|
|
*/
|
2006-02-01 19:05:50 +08:00
|
|
|
static void kmem_freepages(struct kmem_cache *cachep, void *addr)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
unsigned long i = (1 << cachep->gfporder);
|
2005-04-17 06:20:36 +08:00
|
|
|
struct page *page = virt_to_page(addr);
|
|
|
|
const unsigned long nr_freed = i;
|
|
|
|
|
2008-11-25 23:55:53 +08:00
|
|
|
kmemcheck_free_shadow(page, cachep->gfporder);
|
2008-05-10 02:35:53 +08:00
|
|
|
|
2006-09-26 14:31:51 +08: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-17 06:20:36 +08:00
|
|
|
while (i--) {
|
2006-03-22 16:08:02 +08:00
|
|
|
BUG_ON(!PageSlab(page));
|
|
|
|
__ClearPageSlab(page);
|
2005-04-17 06:20:36 +08:00
|
|
|
page++;
|
|
|
|
}
|
|
|
|
if (current->reclaim_state)
|
|
|
|
current->reclaim_state->reclaimed_slab += nr_freed;
|
|
|
|
free_pages((unsigned long)addr, cachep->gfporder);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kmem_rcu_free(struct rcu_head *head)
|
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
struct slab_rcu *slab_rcu = (struct slab_rcu *)head;
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep = slab_rcu->cachep;
|
2005-04-17 06:20:36 +08: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 19:05:50 +08:00
|
|
|
static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
|
2006-01-08 17:00:37 +08:00
|
|
|
unsigned long caller)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:42 +08:00
|
|
|
int size = obj_size(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:42 +08:00
|
|
|
addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
if (size < 5 * sizeof(unsigned long))
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
*addr++ = 0x12345678;
|
|
|
|
*addr++ = caller;
|
|
|
|
*addr++ = smp_processor_id();
|
|
|
|
size -= 3 * sizeof(unsigned long);
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long *sptr = &caller;
|
|
|
|
unsigned long svalue;
|
|
|
|
|
|
|
|
while (!kstack_end(sptr)) {
|
|
|
|
svalue = *sptr++;
|
|
|
|
if (kernel_text_address(svalue)) {
|
2006-01-08 17:00:37 +08:00
|
|
|
*addr++ = svalue;
|
2005-04-17 06:20:36 +08:00
|
|
|
size -= sizeof(unsigned long);
|
|
|
|
if (size <= sizeof(unsigned long))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
*addr++ = 0x87654321;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:42 +08:00
|
|
|
int size = obj_size(cachep);
|
|
|
|
addr = &((char *)addr)[obj_offset(cachep)];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
memset(addr, val, size);
|
2006-01-08 17:00:37 +08:00
|
|
|
*(unsigned char *)(addr + size - 1) = POISON_END;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_line(char *data, int offset, int limit)
|
|
|
|
{
|
|
|
|
int i;
|
2006-09-29 16:59:51 +08:00
|
|
|
unsigned char error = 0;
|
|
|
|
int bad_count = 0;
|
|
|
|
|
2011-07-30 00:22:13 +08:00
|
|
|
printk(KERN_ERR "%03x: ", offset);
|
2006-09-29 16:59:51 +08:00
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
if (data[offset + i] != POISON_FREE) {
|
|
|
|
error = data[offset + i];
|
|
|
|
bad_count++;
|
|
|
|
}
|
|
|
|
}
|
2011-07-30 00:22:13 +08:00
|
|
|
print_hex_dump(KERN_CONT, "", 0, 16, 1,
|
|
|
|
&data[offset], limit, 1);
|
2006-09-29 16:59:51 +08: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-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines)
|
2005-04-17 06:20:36 +08: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 15:22:59 +08:00
|
|
|
printk(KERN_ERR "Redzone: 0x%llx/0x%llx.\n",
|
2006-03-22 16:08:11 +08:00
|
|
|
*dbg_redzone1(cachep, objp),
|
|
|
|
*dbg_redzone2(cachep, objp));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cachep->flags & SLAB_STORE_USER) {
|
|
|
|
printk(KERN_ERR "Last user: [<%p>]",
|
2006-03-22 16:08:11 +08:00
|
|
|
*dbg_userword(cachep, objp));
|
2005-04-17 06:20:36 +08:00
|
|
|
print_symbol("(%s)",
|
2006-03-22 16:08:11 +08:00
|
|
|
(unsigned long)*dbg_userword(cachep, objp));
|
2005-04-17 06:20:36 +08:00
|
|
|
printk("\n");
|
|
|
|
}
|
2006-02-01 19:05:42 +08:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
|
|
|
size = obj_size(cachep);
|
2006-01-08 17:00:37 +08:00
|
|
|
for (i = 0; i < size && lines; i += 16, lines--) {
|
2005-04-17 06:20:36 +08:00
|
|
|
int limit;
|
|
|
|
limit = 16;
|
2006-01-08 17:00:37 +08:00
|
|
|
if (i + limit > size)
|
|
|
|
limit = size - i;
|
2005-04-17 06:20:36 +08:00
|
|
|
dump_line(realobj, i, limit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void check_poison_obj(struct kmem_cache *cachep, void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
char *realobj;
|
|
|
|
int size, i;
|
|
|
|
int lines = 0;
|
|
|
|
|
2006-02-01 19:05:42 +08:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
|
|
|
size = obj_size(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
for (i = 0; i < size; i++) {
|
2005-04-17 06:20:36 +08:00
|
|
|
char exp = POISON_FREE;
|
2006-01-08 17:00:37 +08:00
|
|
|
if (i == size - 1)
|
2005-04-17 06:20:36 +08:00
|
|
|
exp = POISON_END;
|
|
|
|
if (realobj[i] != exp) {
|
|
|
|
int limit;
|
|
|
|
/* Mismatch ! */
|
|
|
|
/* Print header */
|
|
|
|
if (lines == 0) {
|
2006-01-08 17:00:37 +08:00
|
|
|
printk(KERN_ERR
|
2007-04-03 06:46:28 +08:00
|
|
|
"Slab corruption: %s start=%p, len=%d\n",
|
|
|
|
cachep->name, realobj, size);
|
2005-04-17 06:20:36 +08:00
|
|
|
print_objinfo(cachep, objp, 0);
|
|
|
|
}
|
|
|
|
/* Hexdump the affected line */
|
2006-01-08 17:00:37 +08:00
|
|
|
i = (i / 16) * 16;
|
2005-04-17 06:20:36 +08:00
|
|
|
limit = 16;
|
2006-01-08 17:00:37 +08:00
|
|
|
if (i + limit > size)
|
|
|
|
limit = size - i;
|
2005-04-17 06:20:36 +08: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 19:05:49 +08:00
|
|
|
struct slab *slabp = virt_to_slab(objp);
|
2006-03-22 16:08:10 +08:00
|
|
|
unsigned int objnr;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:08:10 +08:00
|
|
|
objnr = obj_to_index(cachep, slabp, objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (objnr) {
|
2006-03-22 16:08:10 +08:00
|
|
|
objp = index_to_obj(cachep, slabp, objnr - 1);
|
2006-02-01 19:05:42 +08:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
|
2006-01-08 17:00:37 +08:00
|
|
|
realobj, size);
|
2005-04-17 06:20:36 +08:00
|
|
|
print_objinfo(cachep, objp, 2);
|
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
if (objnr + 1 < cachep->num) {
|
2006-03-22 16:08:10 +08:00
|
|
|
objp = index_to_obj(cachep, slabp, objnr + 1);
|
2006-02-01 19:05:42 +08:00
|
|
|
realobj = (char *)objp + obj_offset(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
printk(KERN_ERR "Next obj: start=%p, len=%d\n",
|
2006-01-08 17:00:37 +08:00
|
|
|
realobj, size);
|
2005-04-17 06:20:36 +08:00
|
|
|
print_objinfo(cachep, objp, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-01 19:05:46 +08:00
|
|
|
#if DEBUG
|
2008-07-04 03:10:32 +08:00
|
|
|
static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slabp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < cachep->num; i++) {
|
2006-03-22 16:08:10 +08:00
|
|
|
void *objp = index_to_obj(cachep, slabp, i);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_POISON) {
|
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2006-03-22 16:08:11 +08:00
|
|
|
if (cachep->buffer_size % PAGE_SIZE == 0 &&
|
|
|
|
OFF_SLAB(cachep))
|
2006-01-08 17:00:37 +08:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2006-03-22 16:08:11 +08:00
|
|
|
cachep->buffer_size / PAGE_SIZE, 1);
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
"was overwritten");
|
2005-04-17 06:20:36 +08:00
|
|
|
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "end of a freed object "
|
2006-01-08 17:00:37 +08:00
|
|
|
"was overwritten");
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2006-02-01 19:05:46 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
#else
|
2008-07-04 03:10:32 +08:00
|
|
|
static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slabp)
|
2006-02-01 19:05:46 +08:00
|
|
|
{
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
|
2006-03-22 16:08:14 +08:00
|
|
|
/**
|
|
|
|
* slab_destroy - destroy and release all objects in a slab
|
|
|
|
* @cachep: cache pointer being destroyed
|
|
|
|
* @slabp: slab pointer being destroyed
|
|
|
|
*
|
2006-02-01 19:05:46 +08:00
|
|
|
* Destroy all the objs in a slab, and release the mem back to the system.
|
2006-03-22 16:08:11 +08:00
|
|
|
* Before calling the slab must have been unlinked from the cache. The
|
|
|
|
* cache-lock is not held/needed.
|
2006-02-01 19:05:46 +08:00
|
|
|
*/
|
2006-02-01 19:05:50 +08:00
|
|
|
static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
|
2006-02-01 19:05:46 +08:00
|
|
|
{
|
|
|
|
void *addr = slabp->s_mem - slabp->colouroff;
|
|
|
|
|
2008-07-04 03:10:32 +08:00
|
|
|
slab_destroy_debugcheck(cachep, slabp);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
|
|
|
|
struct slab_rcu *slab_rcu;
|
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
slab_rcu = (struct slab_rcu *)slabp;
|
2005-04-17 06:20:36 +08: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 20:44:38 +08:00
|
|
|
if (OFF_SLAB(cachep))
|
|
|
|
kmem_cache_free(cachep->slabp_cache, slabp);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-26 14:31:37 +08:00
|
|
|
static void __kmem_cache_destroy(struct kmem_cache *cachep)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
|
|
|
|
for_each_online_cpu(i)
|
|
|
|
kfree(cachep->array[i]);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
kmem_cache_free(&cache_cache, cachep);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-08 17:00:36 +08:00
|
|
|
/**
|
2006-02-01 19:05:52 +08: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 17:00:36 +08: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 16:08:11 +08:00
|
|
|
static size_t calculate_slab_order(struct kmem_cache *cachep,
|
2006-02-01 19:05:53 +08:00
|
|
|
size_t size, size_t align, unsigned long flags)
|
2006-01-08 17:00:36 +08:00
|
|
|
{
|
2006-06-02 21:44:58 +08:00
|
|
|
unsigned long offslab_limit;
|
2006-01-08 17:00:36 +08:00
|
|
|
size_t left_over = 0;
|
2006-03-07 09:44:43 +08:00
|
|
|
int gfporder;
|
2006-01-08 17:00:36 +08:00
|
|
|
|
2007-05-17 13:11:01 +08:00
|
|
|
for (gfporder = 0; gfporder <= KMALLOC_MAX_ORDER; gfporder++) {
|
2006-01-08 17:00:36 +08:00
|
|
|
unsigned int num;
|
|
|
|
size_t remainder;
|
|
|
|
|
2006-03-07 09:44:43 +08:00
|
|
|
cache_estimate(gfporder, size, align, flags, &remainder, &num);
|
2006-01-08 17:00:36 +08:00
|
|
|
if (!num)
|
|
|
|
continue;
|
2006-03-07 09:44:43 +08:00
|
|
|
|
2006-06-02 21:44:58 +08: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 17:00:36 +08:00
|
|
|
|
2006-03-07 09:44:43 +08:00
|
|
|
/* Found something acceptable - save it away */
|
2006-01-08 17:00:36 +08:00
|
|
|
cachep->num = num;
|
2006-03-07 09:44:43 +08:00
|
|
|
cachep->gfporder = gfporder;
|
2006-01-08 17:00:36 +08:00
|
|
|
left_over = remainder;
|
|
|
|
|
2006-03-09 02:33:05 +08: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 17:00:36 +08:00
|
|
|
/*
|
|
|
|
* Large number of objects is good, but very large slabs are
|
|
|
|
* currently bad for the gfp()s.
|
|
|
|
*/
|
2006-03-07 09:44:43 +08:00
|
|
|
if (gfporder >= slab_break_gfp_order)
|
2006-01-08 17:00:36 +08:00
|
|
|
break;
|
|
|
|
|
2006-03-07 09:44:43 +08:00
|
|
|
/*
|
|
|
|
* Acceptable internal fragmentation?
|
|
|
|
*/
|
2006-03-22 16:08:11 +08:00
|
|
|
if (left_over * 8 <= (PAGE_SIZE << gfporder))
|
2006-01-08 17:00:36 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return left_over;
|
|
|
|
}
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
|
2006-03-22 16:08:11 +08:00
|
|
|
{
|
2006-09-26 14:31:38 +08:00
|
|
|
if (g_cpucache_up == FULL)
|
2009-06-11 00:40:04 +08:00
|
|
|
return enable_cpucache(cachep, gfp);
|
2006-09-26 14:31:38 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
if (g_cpucache_up == NONE) {
|
|
|
|
/*
|
|
|
|
* Note: the first kmem_cache_create must create the cache
|
|
|
|
* 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
|
|
|
|
* the first cache, then we need to set up all its list3s,
|
|
|
|
* otherwise the creation of further caches will BUG().
|
|
|
|
*/
|
|
|
|
set_up_list3s(cachep, SIZE_AC);
|
|
|
|
if (INDEX_AC == INDEX_L3)
|
|
|
|
g_cpucache_up = PARTIAL_L3;
|
|
|
|
else
|
|
|
|
g_cpucache_up = PARTIAL_AC;
|
|
|
|
} else {
|
|
|
|
cachep->array[smp_processor_id()] =
|
2009-06-11 00:40:04 +08:00
|
|
|
kmalloc(sizeof(struct arraycache_init), gfp);
|
2006-03-22 16:08:11 +08:00
|
|
|
|
|
|
|
if (g_cpucache_up == PARTIAL_AC) {
|
|
|
|
set_up_list3s(cachep, SIZE_L3);
|
|
|
|
g_cpucache_up = PARTIAL_L3;
|
|
|
|
} else {
|
|
|
|
int node;
|
2008-01-25 14:20:51 +08:00
|
|
|
for_each_online_node(node) {
|
2006-03-22 16:08:11 +08:00
|
|
|
cachep->nodelists[node] =
|
|
|
|
kmalloc_node(sizeof(struct kmem_list3),
|
2009-06-12 19:56:09 +08:00
|
|
|
gfp, node);
|
2006-03-22 16:08:11 +08: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-27 05:45:03 +08:00
|
|
|
cachep->nodelists[numa_mem_id()]->next_reap =
|
2006-03-22 16:08:11 +08: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 14:31:38 +08:00
|
|
|
return 0;
|
2006-03-22 16:08:11 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/**
|
|
|
|
* kmem_cache_create - Create a cache.
|
|
|
|
* @name: A string which is used in /proc/slabinfo to identify this cache.
|
|
|
|
* @size: The size of objects to be created in this cache.
|
|
|
|
* @align: The required alignment for the objects.
|
|
|
|
* @flags: SLAB flags
|
|
|
|
* @ctor: A constructor for the objects.
|
|
|
|
*
|
|
|
|
* Returns a ptr to the cache on success, NULL on failure.
|
|
|
|
* Cannot be called within a int, but can be interrupted.
|
2007-07-20 09:11:58 +08:00
|
|
|
* The @ctor is run when new pages are allocated by the cache.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* @name must be valid until the cache is destroyed. This implies that
|
2006-03-22 16:08:11 +08:00
|
|
|
* the module calling this has to destroy the cache before getting unloaded.
|
|
|
|
*
|
2005-04-17 06:20:36 +08: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.
|
|
|
|
*/
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *
|
2005-04-17 06:20:36 +08:00
|
|
|
kmem_cache_create (const char *name, size_t size, size_t align,
|
2008-07-26 10:45:34 +08:00
|
|
|
unsigned long flags, void (*ctor)(void *))
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
size_t left_over, slab_size, ralign;
|
2006-06-23 17:03:17 +08:00
|
|
|
struct kmem_cache *cachep = NULL, *pc;
|
2009-06-11 00:40:04 +08:00
|
|
|
gfp_t gfp;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Sanity checks... these are all serious usage bugs.
|
|
|
|
*/
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
|
2007-07-20 09:11:58 +08:00
|
|
|
size > KMALLOC_MAX_SIZE) {
|
2008-04-30 15:55:07 +08:00
|
|
|
printk(KERN_ERR "%s: Early error in slab %s\n", __func__,
|
2006-03-22 16:08:11 +08:00
|
|
|
name);
|
2006-01-08 17:00:37 +08:00
|
|
|
BUG();
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-10 17:51:13 +08: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 12:32:14 +08:00
|
|
|
* We use cache_chain_mutex to ensure a consistent view of
|
2009-01-01 07:42:29 +08:00
|
|
|
* cpu_online_mask as well. Please see cpuup_callback
|
2006-02-10 17:51:13 +08:00
|
|
|
*/
|
2009-06-11 00:40:04 +08:00
|
|
|
if (slab_is_available()) {
|
|
|
|
get_online_cpus();
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
}
|
2005-11-07 16:58:00 +08:00
|
|
|
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(pc, &cache_chain, next) {
|
2005-11-07 16:58:00 +08:00
|
|
|
char tmp;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This happens when the module gets unloaded and doesn't
|
|
|
|
* destroy its slab cache and no-one else reuses the vmalloc
|
|
|
|
* area of the module. Print a warning.
|
|
|
|
*/
|
2006-12-07 12:36:41 +08:00
|
|
|
res = probe_kernel_address(pc->name, tmp);
|
2005-11-07 16:58:00 +08:00
|
|
|
if (res) {
|
2007-05-07 05:49:52 +08:00
|
|
|
printk(KERN_ERR
|
|
|
|
"SLAB: cache with size %d has lost its name\n",
|
2006-02-01 19:05:42 +08:00
|
|
|
pc->buffer_size);
|
2005-11-07 16:58:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
if (!strcmp(pc->name, name)) {
|
2007-05-07 05:49:52 +08:00
|
|
|
printk(KERN_ERR
|
|
|
|
"kmem_cache_create: duplicate cache %s\n", name);
|
2005-11-07 16:58:00 +08:00
|
|
|
dump_stack();
|
|
|
|
goto oops;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#if DEBUG
|
|
|
|
WARN_ON(strchr(name, ' ')); /* It confuses parsers */
|
|
|
|
#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 09:26:44 +08:00
|
|
|
if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
|
|
|
|
2 * sizeof(unsigned long long)))
|
2006-01-08 17:00:37 +08:00
|
|
|
flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
* Always checks flags, a caller might be expecting debug support which
|
|
|
|
* isn't available.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2006-04-02 19:49:25 +08:00
|
|
|
BUG_ON(flags & ~CREATE_MASK);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Check that size is in terms of words. This is needed to avoid
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
if (size & (BYTES_PER_WORD - 1)) {
|
|
|
|
size += (BYTES_PER_WORD - 1);
|
|
|
|
size &= ~(BYTES_PER_WORD - 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/* calculate the final buffer alignment: */
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* 1) arch recommendation: can be overridden for debug */
|
|
|
|
if (flags & SLAB_HWCACHE_ALIGN) {
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Default alignment: as specified by the arch code. Except if
|
|
|
|
* an object is really small, then squeeze multiple objects into
|
|
|
|
* one cacheline.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
ralign = cache_line_size();
|
2006-01-08 17:00:37 +08:00
|
|
|
while (size <= ralign / 2)
|
2005-04-17 06:20:36 +08:00
|
|
|
ralign /= 2;
|
|
|
|
} else {
|
|
|
|
ralign = BYTES_PER_WORD;
|
|
|
|
}
|
2006-09-26 14:31:25 +08: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 09:26:44 +08: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 14:31:25 +08: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 09:26:44 +08: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 14:31:25 +08:00
|
|
|
|
2006-12-07 12:32:11 +08:00
|
|
|
/* 2) arch mandated alignment */
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ralign < ARCH_SLAB_MINALIGN) {
|
|
|
|
ralign = ARCH_SLAB_MINALIGN;
|
|
|
|
}
|
2006-12-07 12:32:11 +08:00
|
|
|
/* 3) caller mandated alignment */
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ralign < align) {
|
|
|
|
ralign = align;
|
|
|
|
}
|
2011-02-14 23:46:21 +08:00
|
|
|
/* disable debug if necessary */
|
|
|
|
if (ralign > __alignof__(unsigned long long))
|
2006-12-07 12:32:11 +08:00
|
|
|
flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
2006-09-26 14:31:25 +08:00
|
|
|
* 4) Store it.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
align = ralign;
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
if (slab_is_available())
|
|
|
|
gfp = GFP_KERNEL;
|
|
|
|
else
|
|
|
|
gfp = GFP_NOWAIT;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Get cache's description obj. */
|
2009-06-11 00:40:04 +08:00
|
|
|
cachep = kmem_cache_zalloc(&cache_cache, gfp);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!cachep)
|
2005-11-07 16:58:00 +08:00
|
|
|
goto oops;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-21 01:04:23 +08:00
|
|
|
cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
|
2005-04-17 06:20:36 +08:00
|
|
|
#if DEBUG
|
2006-02-01 19:05:42 +08:00
|
|
|
cachep->obj_size = size;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-09-26 14:31:25 +08:00
|
|
|
/*
|
|
|
|
* Both debugging options require word-alignment which is calculated
|
|
|
|
* into align above.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
if (flags & SLAB_RED_ZONE) {
|
|
|
|
/* add space for red zone words */
|
2011-02-14 23:46:21 +08:00
|
|
|
cachep->obj_offset += sizeof(unsigned long long);
|
|
|
|
size += 2 * sizeof(unsigned long long);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
if (flags & SLAB_STORE_USER) {
|
2006-09-26 14:31:25 +08: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 09:26:44 +08: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-17 06:20:36 +08: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 09:26:44 +08:00
|
|
|
if (flags & SLAB_RED_ZONE)
|
|
|
|
size += REDZONE_ALIGN;
|
|
|
|
else
|
|
|
|
size += BYTES_PER_WORD;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
|
2006-01-08 17:00:37 +08:00
|
|
|
if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
|
2010-08-07 00:19:22 +08:00
|
|
|
&& cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) {
|
|
|
|
cachep->obj_offset += PAGE_SIZE - ALIGN(size, align);
|
2005-04-17 06:20:36 +08:00
|
|
|
size = PAGE_SIZE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2006-06-23 17:03:46 +08:00
|
|
|
/*
|
|
|
|
* Determine if the slab management is 'on' or 'off' slab.
|
|
|
|
* (bootstrapping cannot cope with offslab caches so don't do
|
2009-10-28 21:33:08 +08:00
|
|
|
* it too early on. Always use on-slab management when
|
|
|
|
* SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
|
2006-06-23 17:03:46 +08:00
|
|
|
*/
|
2009-10-28 21:33:08 +08:00
|
|
|
if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
|
|
|
|
!(flags & SLAB_NOLEAKTRACE))
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Size is large, assume best to place the slab management obj
|
|
|
|
* off-slab (should allow better packing of objs).
|
|
|
|
*/
|
|
|
|
flags |= CFLGS_OFF_SLAB;
|
|
|
|
|
|
|
|
size = ALIGN(size, align);
|
|
|
|
|
2006-03-09 02:33:05 +08:00
|
|
|
left_over = calculate_slab_order(cachep, size, align, flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!cachep->num) {
|
2007-05-07 05:49:52 +08:00
|
|
|
printk(KERN_ERR
|
|
|
|
"kmem_cache_create: couldn't create cache %s.\n", name);
|
2005-04-17 06:20:36 +08:00
|
|
|
kmem_cache_free(&cache_cache, cachep);
|
|
|
|
cachep = NULL;
|
2005-11-07 16:58:00 +08:00
|
|
|
goto oops;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
|
|
|
|
+ sizeof(struct slab), align);
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
slab_size =
|
|
|
|
cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
|
2009-05-22 03:28:22 +08: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-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cachep->colour_off = cache_line_size();
|
|
|
|
/* Offset must be a multiple of the alignment. */
|
|
|
|
if (cachep->colour_off < align)
|
|
|
|
cachep->colour_off = align;
|
2006-01-08 17:00:37 +08:00
|
|
|
cachep->colour = left_over / cachep->colour_off;
|
2005-04-17 06:20:36 +08:00
|
|
|
cachep->slab_size = slab_size;
|
|
|
|
cachep->flags = flags;
|
|
|
|
cachep->gfpflags = 0;
|
2007-02-10 17:43:10 +08:00
|
|
|
if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
|
2005-04-17 06:20:36 +08:00
|
|
|
cachep->gfpflags |= GFP_DMA;
|
2006-02-01 19:05:42 +08:00
|
|
|
cachep->buffer_size = size;
|
2006-12-13 16:34:27 +08:00
|
|
|
cachep->reciprocal_buffer_size = reciprocal_value(size);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-09-26 14:31:34 +08:00
|
|
|
if (flags & CFLGS_OFF_SLAB) {
|
2005-09-10 15:26:36 +08:00
|
|
|
cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
|
2006-09-26 14:31:34 +08: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 19:03:22 +08:00
|
|
|
BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
|
2006-09-26 14:31:34 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
cachep->ctor = ctor;
|
|
|
|
cachep->name = name;
|
|
|
|
|
2009-06-11 00:40:04 +08:00
|
|
|
if (setup_cpu_cache(cachep, gfp)) {
|
2006-09-26 14:31:38 +08:00
|
|
|
__kmem_cache_destroy(cachep);
|
|
|
|
cachep = NULL;
|
|
|
|
goto oops;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-22 21:26:05 +08: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);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* cache setup completed, link it into the list */
|
|
|
|
list_add(&cachep->next, &cache_chain);
|
2006-03-22 16:08:11 +08:00
|
|
|
oops:
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!cachep && (flags & SLAB_PANIC))
|
|
|
|
panic("kmem_cache_create(): failed to create slab `%s'\n",
|
2006-01-08 17:00:37 +08:00
|
|
|
name);
|
2009-06-11 00:40:04 +08:00
|
|
|
if (slab_is_available()) {
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
|
|
|
put_online_cpus();
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
return cachep;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_create);
|
|
|
|
|
|
|
|
#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 19:05:50 +08:00
|
|
|
static void check_spinlock_acquired(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08: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-27 05:45:03 +08:00
|
|
|
assert_spin_locked(&cachep->nodelists[numa_mem_id()]->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
}
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void check_spinlock_acquired_node(struct kmem_cache *cachep, int node)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
check_irq_off();
|
|
|
|
assert_spin_locked(&cachep->nodelists[node]->list_lock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
#define check_spinlock_acquired_node(x, y) do { } while(0)
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
|
2006-03-22 16:09:06 +08:00
|
|
|
static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
|
|
|
|
struct array_cache *ac,
|
|
|
|
int force, int node);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void do_drain(void *arg)
|
|
|
|
{
|
2006-03-22 16:08:11 +08:00
|
|
|
struct kmem_cache *cachep = arg;
|
2005-04-17 06:20:36 +08: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-27 05:45:03 +08:00
|
|
|
int node = numa_mem_id();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
check_irq_off();
|
2006-02-01 19:05:49 +08:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-09-23 12:44:02 +08: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-17 06:20:36 +08:00
|
|
|
ac->avail = 0;
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void drain_cpu_caches(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2005-09-10 04:03:32 +08:00
|
|
|
struct kmem_list3 *l3;
|
|
|
|
int node;
|
|
|
|
|
2008-05-09 15:39:44 +08:00
|
|
|
on_each_cpu(do_drain, cachep, 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
check_irq_on();
|
2006-01-08 17:00:37 +08:00
|
|
|
for_each_online_node(node) {
|
2005-09-10 04:03:32 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-05-16 02:41:00 +08: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 16:09:06 +08:00
|
|
|
drain_array(cachep, l3, l3->shared, 1, node);
|
2005-09-10 04:03:32 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-06-30 16:55:45 +08: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-17 06:20:36 +08:00
|
|
|
{
|
2006-06-30 16:55:45 +08:00
|
|
|
struct list_head *p;
|
|
|
|
int nr_freed;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct slab *slabp;
|
|
|
|
|
2006-06-30 16:55:45 +08:00
|
|
|
nr_freed = 0;
|
|
|
|
while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-30 16:55:45 +08:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
2005-09-10 04:03:32 +08:00
|
|
|
p = l3->slabs_free.prev;
|
2006-06-30 16:55:45 +08:00
|
|
|
if (p == &l3->slabs_free) {
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-30 16:55:45 +08:00
|
|
|
slabp = list_entry(p, struct slab, list);
|
2005-04-17 06:20:36 +08:00
|
|
|
#if DEBUG
|
2006-04-02 19:49:25 +08:00
|
|
|
BUG_ON(slabp->inuse);
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
list_del(&slabp->list);
|
2006-06-30 16:55:45 +08:00
|
|
|
/*
|
|
|
|
* Safe to drop the lock. The slab is no longer linked
|
|
|
|
* to the cache.
|
|
|
|
*/
|
|
|
|
l3->free_objects -= cache->num;
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2006-06-30 16:55:45 +08:00
|
|
|
slab_destroy(cache, slabp);
|
|
|
|
nr_freed++;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-06-30 16:55:45 +08:00
|
|
|
out:
|
|
|
|
return nr_freed;
|
2005-04-17 06:20:36 +08: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 12:32:14 +08:00
|
|
|
/* Called with cache_chain_mutex held to protect against cpu hotplug */
|
2006-02-01 19:05:50 +08:00
|
|
|
static int __cache_shrink(struct kmem_cache *cachep)
|
2005-09-10 04:03:32 +08: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 16:55:45 +08:00
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drain_freelist(cachep, l3, l3->free_objects);
|
|
|
|
|
|
|
|
ret += !list_empty(&l3->slabs_full) ||
|
|
|
|
!list_empty(&l3->slabs_partial);
|
2005-09-10 04:03:32 +08:00
|
|
|
}
|
|
|
|
return (ret ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08: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 19:05:50 +08:00
|
|
|
int kmem_cache_shrink(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08: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 12:32:14 +08:00
|
|
|
int ret;
|
2006-04-02 19:49:25 +08:00
|
|
|
BUG_ON(!cachep || in_interrupt());
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-01-26 04:08:02 +08:00
|
|
|
get_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 12:32:14 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
ret = __cache_shrink(cachep);
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2008-01-26 04:08:02 +08: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 12:32:14 +08:00
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_shrink);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* kmem_cache_destroy - delete a cache
|
|
|
|
* @cachep: the cache to destroy
|
|
|
|
*
|
2007-02-10 17:45:59 +08:00
|
|
|
* Remove a &struct kmem_cache object from the slab cache.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* It is expected this function will be called by a module when it is
|
|
|
|
* unloaded. This will remove the cache completely, and avoid a duplicate
|
|
|
|
* cache being allocated each time a module is loaded and unloaded, if the
|
|
|
|
* module doesn't have persistent in-kernel storage across loads and unloads.
|
|
|
|
*
|
|
|
|
* The cache must be empty before calling this function.
|
|
|
|
*
|
2011-03-31 09:57:33 +08:00
|
|
|
* The caller must guarantee that no one will allocate memory from the cache
|
2005-04-17 06:20:36 +08:00
|
|
|
* during the kmem_cache_destroy().
|
|
|
|
*/
|
[PATCH] Make kmem_cache_destroy() return void
un-, de-, -free, -destroy, -exit, etc functions should in general return
void. Also,
There is very little, say, filesystem driver code can do upon failed
kmem_cache_destroy(). If it will be decided to BUG in this case, BUG
should be put in generic code, instead.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-27 16:49:41 +08:00
|
|
|
void kmem_cache_destroy(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-04-02 19:49:25 +08:00
|
|
|
BUG_ON(!cachep || in_interrupt());
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Find the cache in the chain of caches. */
|
2008-01-26 04:08:02 +08:00
|
|
|
get_online_cpus();
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* the chain is never empty, cache_cache is never destroyed
|
|
|
|
*/
|
|
|
|
list_del(&cachep->next);
|
|
|
|
if (__cache_shrink(cachep)) {
|
|
|
|
slab_error(cachep, "Can't free all objects");
|
2006-01-08 17:00:37 +08:00
|
|
|
list_add(&cachep->next, &cache_chain);
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2008-01-26 04:08:02 +08:00
|
|
|
put_online_cpus();
|
[PATCH] Make kmem_cache_destroy() return void
un-, de-, -free, -destroy, -exit, etc functions should in general return
void. Also,
There is very little, say, filesystem driver code can do upon failed
kmem_cache_destroy(). If it will be decided to BUG in this case, BUG
should be put in generic code, instead.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-27 16:49:41 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
|
2009-06-26 03:31:37 +08:00
|
|
|
rcu_barrier();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-09-26 14:31:37 +08:00
|
|
|
__kmem_cache_destroy(cachep);
|
[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 12:32:14 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2008-01-26 04:08:02 +08:00
|
|
|
put_online_cpus();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_destroy);
|
|
|
|
|
2006-09-26 14:31:34 +08: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 19:05:50 +08:00
|
|
|
static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
|
2006-04-11 13:52:53 +08:00
|
|
|
int colour_off, gfp_t local_flags,
|
|
|
|
int nodeid)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct slab *slabp;
|
2006-01-08 17:00:37 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (OFF_SLAB(cachep)) {
|
|
|
|
/* Slab management obj is off-slab. */
|
2006-04-11 13:52:53 +08:00
|
|
|
slabp = kmem_cache_alloc_node(cachep->slabp_cache,
|
2008-11-26 16:01:31 +08:00
|
|
|
local_flags, nodeid);
|
2009-06-11 20:22:40 +08: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 21:33:09 +08:00
|
|
|
kmemleak_scan_area(&slabp->list, sizeof(struct list_head),
|
|
|
|
local_flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!slabp)
|
|
|
|
return NULL;
|
|
|
|
} else {
|
2006-01-08 17:00:37 +08:00
|
|
|
slabp = objp + colour_off;
|
2005-04-17 06:20:36 +08:00
|
|
|
colour_off += cachep->slab_size;
|
|
|
|
}
|
|
|
|
slabp->inuse = 0;
|
|
|
|
slabp->colouroff = colour_off;
|
2006-01-08 17:00:37 +08:00
|
|
|
slabp->s_mem = objp + colour_off;
|
2006-04-11 13:52:53 +08:00
|
|
|
slabp->nodeid = nodeid;
|
2008-02-10 18:21:54 +08:00
|
|
|
slabp->free = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
return slabp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
|
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
return (kmem_bufctl_t *) (slabp + 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void cache_init_objs(struct kmem_cache *cachep,
|
2007-05-17 13:10:57 +08:00
|
|
|
struct slab *slabp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < cachep->num; i++) {
|
2006-03-22 16:08:10 +08:00
|
|
|
void *objp = index_to_obj(cachep, slabp, i);
|
2005-04-17 06:20:36 +08: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 16:08:11 +08: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-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
|
2008-07-26 10:45:34 +08:00
|
|
|
cachep->ctor(objp + obj_offset(cachep));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
|
|
|
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "constructor overwrote the"
|
2006-01-08 17:00:37 +08:00
|
|
|
" end of an object");
|
2005-04-17 06:20:36 +08:00
|
|
|
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
|
|
|
|
slab_error(cachep, "constructor overwrote the"
|
2006-01-08 17:00:37 +08:00
|
|
|
" start of an object");
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-03-22 16:08:11 +08:00
|
|
|
if ((cachep->buffer_size % PAGE_SIZE) == 0 &&
|
|
|
|
OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
|
2006-01-08 17:00:37 +08:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2006-02-01 19:05:42 +08:00
|
|
|
cachep->buffer_size / PAGE_SIZE, 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
#else
|
|
|
|
if (cachep->ctor)
|
2008-07-26 10:45:34 +08:00
|
|
|
cachep->ctor(objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
2006-01-08 17:00:37 +08:00
|
|
|
slab_bufctl(slabp)[i] = i + 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
slab_bufctl(slabp)[i - 1] = BUFCTL_END;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-02-10 17:43:10 +08:00
|
|
|
if (CONFIG_ZONE_DMA_FLAG) {
|
|
|
|
if (flags & GFP_DMA)
|
|
|
|
BUG_ON(!(cachep->gfpflags & GFP_DMA));
|
|
|
|
else
|
|
|
|
BUG_ON(cachep->gfpflags & GFP_DMA);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
static void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp,
|
|
|
|
int nodeid)
|
2006-02-01 19:05:47 +08:00
|
|
|
{
|
2006-03-22 16:08:10 +08:00
|
|
|
void *objp = index_to_obj(cachep, slabp, slabp->free);
|
2006-02-01 19:05:47 +08: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 16:08:11 +08:00
|
|
|
static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp,
|
|
|
|
void *objp, int nodeid)
|
2006-02-01 19:05:47 +08:00
|
|
|
{
|
2006-03-22 16:08:10 +08:00
|
|
|
unsigned int objnr = obj_to_index(cachep, slabp, objp);
|
2006-02-01 19:05:47 +08:00
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
/* Verify that the slab belongs to the intended node */
|
|
|
|
WARN_ON(slabp->nodeid != nodeid);
|
|
|
|
|
2006-03-25 19:06:39 +08:00
|
|
|
if (slab_bufctl(slabp)[objnr] + 1 <= SLAB_LIMIT + 1) {
|
2006-02-01 19:05:47 +08:00
|
|
|
printk(KERN_ERR "slab: double free detected in cache "
|
2006-03-22 16:08:11 +08:00
|
|
|
"'%s', objp %p\n", cachep->name, objp);
|
2006-02-01 19:05:47 +08:00
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
slab_bufctl(slabp)[objnr] = slabp->free;
|
|
|
|
slabp->free = objnr;
|
|
|
|
slabp->inuse--;
|
|
|
|
}
|
|
|
|
|
2006-06-23 17:03:07 +08: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 14:49:17 +08:00
|
|
|
* virtual address for kfree, ksize, and slab debugging.
|
2006-06-23 17:03:07 +08:00
|
|
|
*/
|
|
|
|
static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
|
|
|
|
void *addr)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-06-23 17:03:07 +08:00
|
|
|
int nr_pages;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct page *page;
|
|
|
|
|
2006-06-23 17:03:07 +08:00
|
|
|
page = virt_to_page(addr);
|
2006-03-22 16:08:34 +08:00
|
|
|
|
2006-06-23 17:03:07 +08:00
|
|
|
nr_pages = 1;
|
2006-03-22 16:08:34 +08:00
|
|
|
if (likely(!PageCompound(page)))
|
2006-06-23 17:03:07 +08:00
|
|
|
nr_pages <<= cache->gfporder;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
do {
|
2006-06-23 17:03:07 +08:00
|
|
|
page_set_cache(page, cache);
|
|
|
|
page_set_slab(page, slab);
|
2005-04-17 06:20:36 +08:00
|
|
|
page++;
|
2006-06-23 17:03:07 +08:00
|
|
|
} while (--nr_pages);
|
2005-04-17 06:20:36 +08: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 12:33:29 +08:00
|
|
|
static int cache_grow(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags, int nodeid, void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
struct slab *slabp;
|
|
|
|
size_t offset;
|
|
|
|
gfp_t local_flags;
|
2005-09-10 04:03:32 +08:00
|
|
|
struct kmem_list3 *l3;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Be lazy and only check for valid flags here, keeping it out of the
|
|
|
|
* critical path in kmem_cache_alloc().
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-10-16 16:25:41 +08:00
|
|
|
BUG_ON(flags & GFP_SLAB_BUG_MASK);
|
|
|
|
local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-05 15:27:56 +08:00
|
|
|
/* Take the l3 list lock to change the colour_next on this node */
|
2005-04-17 06:20:36 +08:00
|
|
|
check_irq_off();
|
2006-02-05 15:27:56 +08:00
|
|
|
l3 = cachep->nodelists[nodeid];
|
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Get colour for the slab, and cal the next value. */
|
2006-02-05 15:27:56 +08: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-17 06:20:36 +08:00
|
|
|
|
2006-02-05 15:27:56 +08:00
|
|
|
offset *= cachep->colour_off;
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* Get mem for the objs. Attempt to allocate a physical page from
|
|
|
|
* 'nodeid'.
|
2005-09-10 04:03:32 +08:00
|
|
|
*/
|
2006-12-07 12:33:29 +08:00
|
|
|
if (!objp)
|
2007-07-25 03:02:40 +08:00
|
|
|
objp = kmem_getpages(cachep, local_flags, nodeid);
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto failed;
|
|
|
|
|
|
|
|
/* Get slab management. */
|
2006-12-07 12:33:29 +08:00
|
|
|
slabp = alloc_slabmgmt(cachep, objp, offset,
|
2007-10-16 16:25:41 +08:00
|
|
|
local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!slabp)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto opps1;
|
|
|
|
|
2006-06-23 17:03:07 +08:00
|
|
|
slab_map_pages(cachep, slabp, objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-05-17 13:10:57 +08:00
|
|
|
cache_init_objs(cachep, slabp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_disable();
|
|
|
|
check_irq_off();
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Make slab active. */
|
2005-09-10 04:03:32 +08:00
|
|
|
list_add_tail(&slabp->list, &(l3->slabs_free));
|
2005-04-17 06:20:36 +08:00
|
|
|
STATS_INC_GROWN(cachep);
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->free_objects += cachep->num;
|
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 1;
|
2006-03-22 16:08:11 +08:00
|
|
|
opps1:
|
2005-04-17 06:20:36 +08:00
|
|
|
kmem_freepages(cachep, objp);
|
2006-03-22 16:08:11 +08:00
|
|
|
failed:
|
2005-04-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
(unsigned long)objp);
|
|
|
|
BUG();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-23 17:03:24 +08: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 15:22:59 +08:00
|
|
|
unsigned long long redzone1, redzone2;
|
2006-06-23 17:03:24 +08: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 15:22:59 +08:00
|
|
|
printk(KERN_ERR "%p: redzone 1:0x%llx, redzone 2:0x%llx.\n",
|
2006-06-23 17:03:24 +08:00
|
|
|
obj, redzone1, redzone2);
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
|
2006-01-08 17:00:37 +08:00
|
|
|
void *caller)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct page *page;
|
|
|
|
unsigned int objnr;
|
|
|
|
struct slab *slabp;
|
|
|
|
|
2007-11-30 03:05:13 +08:00
|
|
|
BUG_ON(virt_to_cache(objp) != cachep);
|
|
|
|
|
2006-02-01 19:05:42 +08:00
|
|
|
objp -= obj_offset(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree_debugcheck(objp);
|
2007-05-07 05:49:41 +08:00
|
|
|
page = virt_to_head_page(objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-11-14 08:06:46 +08:00
|
|
|
slabp = page_get_slab(page);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
2006-06-23 17:03:24 +08:00
|
|
|
verify_redzone_free(cachep, objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
|
|
|
|
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
|
|
|
|
}
|
|
|
|
if (cachep->flags & SLAB_STORE_USER)
|
|
|
|
*dbg_userword(cachep, objp) = caller;
|
|
|
|
|
2006-03-22 16:08:10 +08:00
|
|
|
objnr = obj_to_index(cachep, slabp, objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
BUG_ON(objnr >= cachep->num);
|
2006-03-22 16:08:10 +08:00
|
|
|
BUG_ON(objp != index_to_obj(cachep, slabp, objnr));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-25 19:06:39 +08:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
slab_bufctl(slabp)[objnr] = BUFCTL_FREE;
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
if (cachep->flags & SLAB_POISON) {
|
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2006-03-22 16:08:11 +08:00
|
|
|
if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
store_stackinfo(cachep, objp, (unsigned long)caller);
|
2006-01-08 17:00:37 +08:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2006-02-01 19:05:42 +08:00
|
|
|
cachep->buffer_size / PAGE_SIZE, 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
|
|
|
poison_obj(cachep, objp, POISON_FREE);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
poison_obj(cachep, objp, POISON_FREE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void check_slabp(struct kmem_cache *cachep, struct slab *slabp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
kmem_bufctl_t i;
|
|
|
|
int entries = 0;
|
2006-01-08 17:00:37 +08:00
|
|
|
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
bad:
|
|
|
|
printk(KERN_ERR "slab: Internal list corruption detected in "
|
|
|
|
"cache '%s'(%d), slabp %p(%d). Hexdump:\n",
|
|
|
|
cachep->name, cachep->num, slabp, slabp->inuse);
|
2011-07-30 00:22:13 +08:00
|
|
|
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, slabp,
|
|
|
|
sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t),
|
|
|
|
1);
|
2005-04-17 06:20:36 +08: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
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int batchcount;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
struct array_cache *ac;
|
2006-10-06 15:43:52 +08:00
|
|
|
int node;
|
|
|
|
|
2008-03-06 07:04:59 +08:00
|
|
|
retry:
|
2005-04-17 06:20:36 +08: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-27 05:45:03 +08:00
|
|
|
node = numa_mem_id();
|
2006-02-01 19:05:49 +08:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
batchcount = ac->batchcount;
|
|
|
|
if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* If there was little recent activity on this cache, then
|
|
|
|
* perform only a partial refill. Otherwise we could generate
|
|
|
|
* refill bouncing.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
batchcount = BATCHREFILL_LIMIT;
|
|
|
|
}
|
2006-10-06 15:43:52 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
2005-09-10 04:03:32 +08:00
|
|
|
|
|
|
|
BUG_ON(ac->avail > 0 || !l3);
|
|
|
|
spin_lock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-25 19:06:44 +08:00
|
|
|
/* See if we can refill from the shared array */
|
2010-01-27 19:27:40 +08:00
|
|
|
if (l3->shared && transfer_objects(ac, l3->shared, batchcount)) {
|
|
|
|
l3->shared->touched = 1;
|
2006-03-25 19:06:44 +08:00
|
|
|
goto alloc_done;
|
2010-01-27 19:27:40 +08:00
|
|
|
}
|
2006-03-25 19:06:44 +08:00
|
|
|
|
2005-04-17 06:20:36 +08: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-07 05:49:03 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The slab was either on partial or free list so
|
|
|
|
* there must be at least one object available for
|
|
|
|
* allocation.
|
|
|
|
*/
|
2008-10-30 05:18:07 +08:00
|
|
|
BUG_ON(slabp->inuse >= cachep->num);
|
2007-05-07 05:49:03 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
while (slabp->inuse < cachep->num && batchcount--) {
|
|
|
|
STATS_INC_ALLOCED(cachep);
|
|
|
|
STATS_INC_ACTIVE(cachep);
|
|
|
|
STATS_SET_HIGH(cachep);
|
|
|
|
|
2006-02-01 19:05:47 +08:00
|
|
|
ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
|
2006-10-06 15:43:52 +08:00
|
|
|
node);
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
must_grow:
|
2005-04-17 06:20:36 +08:00
|
|
|
l3->free_objects -= ac->avail;
|
2006-03-22 16:08:11 +08:00
|
|
|
alloc_done:
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (unlikely(!ac->avail)) {
|
|
|
|
int x;
|
2006-12-07 12:33:29 +08:00
|
|
|
x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/* cache_grow can reenable interrupts, then ac could change. */
|
2006-02-01 19:05:49 +08:00
|
|
|
ac = cpu_cache_get(cachep);
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!x && ac->avail == 0) /* no objects in sight? abort */
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
if (!ac->avail) /* objects refilled by interrupt? */
|
2005-04-17 06:20:36 +08:00
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
ac->touched = 1;
|
2005-09-10 04:03:32 +08:00
|
|
|
return ac->entry[--ac->avail];
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
might_sleep_if(flags & __GFP_WAIT);
|
|
|
|
#if DEBUG
|
|
|
|
kmem_flagcheck(cachep, flags);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG
|
2006-03-22 16:08:11 +08:00
|
|
|
static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
|
|
|
|
gfp_t flags, void *objp, void *caller)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
if (!objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
return objp;
|
2006-01-08 17:00:37 +08:00
|
|
|
if (cachep->flags & SLAB_POISON) {
|
2005-04-17 06:20:36 +08:00
|
|
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
2006-02-01 19:05:42 +08:00
|
|
|
if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
|
2006-01-08 17:00:37 +08:00
|
|
|
kernel_map_pages(virt_to_page(objp),
|
2006-02-01 19:05:42 +08:00
|
|
|
cachep->buffer_size / PAGE_SIZE, 1);
|
2005-04-17 06:20:36 +08: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)
|
|
|
|
*dbg_userword(cachep, objp) = caller;
|
|
|
|
|
|
|
|
if (cachep->flags & SLAB_RED_ZONE) {
|
2006-03-22 16:08:11 +08: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 17:00:37 +08: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 15:22:59 +08:00
|
|
|
"%p: redzone 1:0x%llx, redzone 2:0x%llx\n",
|
2006-03-22 16:08:11 +08:00
|
|
|
objp, *dbg_redzone1(cachep, objp),
|
|
|
|
*dbg_redzone2(cachep, objp));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
*dbg_redzone1(cachep, objp) = RED_ACTIVE;
|
|
|
|
*dbg_redzone2(cachep, objp) = RED_ACTIVE;
|
|
|
|
}
|
2006-03-25 19:06:39 +08:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
{
|
|
|
|
struct slab *slabp;
|
|
|
|
unsigned objnr;
|
|
|
|
|
2007-05-07 05:49:41 +08:00
|
|
|
slabp = page_get_slab(virt_to_head_page(objp));
|
2006-03-25 19:06:39 +08:00
|
|
|
objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
|
|
|
|
slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE;
|
|
|
|
}
|
|
|
|
#endif
|
2006-02-01 19:05:42 +08:00
|
|
|
objp += obj_offset(cachep);
|
2007-05-07 05:50:17 +08:00
|
|
|
if (cachep->ctor && cachep->flags & SLAB_POISON)
|
2008-07-26 10:45:34 +08:00
|
|
|
cachep->ctor(objp);
|
2011-07-21 08:42:45 +08:00
|
|
|
if (ARCH_SLAB_MINALIGN &&
|
|
|
|
((unsigned long)objp & (ARCH_SLAB_MINALIGN-1))) {
|
2006-12-07 12:32:11 +08:00
|
|
|
printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n",
|
2011-07-12 04:35:08 +08:00
|
|
|
objp, (int)ARCH_SLAB_MINALIGN);
|
2006-12-07 12:32:11 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
|
|
|
|
#endif
|
|
|
|
|
2008-12-23 18:37:01 +08:00
|
|
|
static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
|
2006-12-08 18:39:44 +08:00
|
|
|
{
|
|
|
|
if (cachep == &cache_cache)
|
2008-12-23 18:37:01 +08:00
|
|
|
return false;
|
2006-12-08 18:39:44 +08:00
|
|
|
|
2010-02-26 14:36:12 +08:00
|
|
|
return should_failslab(obj_size(cachep), flags, cachep->flags);
|
2006-12-08 18:39:44 +08:00
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
void *objp;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct array_cache *ac;
|
|
|
|
|
2005-09-28 12:45:46 +08:00
|
|
|
check_irq_off();
|
2006-12-08 18:39:44 +08:00
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
ac = cpu_cache_get(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (likely(ac->avail)) {
|
|
|
|
STATS_INC_ALLOCHIT(cachep);
|
|
|
|
ac->touched = 1;
|
2005-09-10 04:03:32 +08:00
|
|
|
objp = ac->entry[--ac->avail];
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
|
|
|
STATS_INC_ALLOCMISS(cachep);
|
|
|
|
objp = cache_alloc_refill(cachep, flags);
|
2009-12-02 15:55:50 +08:00
|
|
|
/*
|
|
|
|
* the 'ac' may be updated by cache_alloc_refill(),
|
|
|
|
* and kmemleak_erase() requires its correct value.
|
|
|
|
*/
|
|
|
|
ac = cpu_cache_get(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2009-06-11 20:22:40 +08: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 15:55:49 +08:00
|
|
|
if (objp)
|
|
|
|
kmemleak_erase(&ac->entry[ac->avail]);
|
2005-09-28 12:45:46 +08:00
|
|
|
return objp;
|
|
|
|
}
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
#ifdef CONFIG_NUMA
|
2006-03-24 19:16:08 +08:00
|
|
|
/*
|
2006-03-24 19:16:12 +08:00
|
|
|
* Try allocating on another node if PF_SPREAD_SLAB|PF_MEMPOLICY.
|
2006-03-24 19:16:08 +08: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 16:50:08 +08:00
|
|
|
if (in_interrupt() || (flags & __GFP_THISNODE))
|
2006-03-24 19:16:08 +08: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-27 05:45:03 +08:00
|
|
|
nid_alloc = nid_here = numa_mem_id();
|
2010-05-25 05:32:08 +08:00
|
|
|
get_mems_allowed();
|
2006-03-24 19:16:08 +08:00
|
|
|
if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
|
2010-05-27 05:42:49 +08:00
|
|
|
nid_alloc = cpuset_slab_spread_node();
|
2006-03-24 19:16:08 +08:00
|
|
|
else if (current->mempolicy)
|
|
|
|
nid_alloc = slab_node(current->mempolicy);
|
2010-05-25 05:32:08 +08:00
|
|
|
put_mems_allowed();
|
2006-03-24 19:16:08 +08:00
|
|
|
if (nid_alloc != nid_here)
|
2006-12-07 12:32:30 +08:00
|
|
|
return ____cache_alloc_node(cachep, flags, nid_alloc);
|
2006-03-24 19:16:08 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-09-27 16:50:08 +08:00
|
|
|
/*
|
|
|
|
* Fallback function if there was no memory available and no objects on a
|
2006-12-07 12:33:29 +08: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 16:50:08 +08:00
|
|
|
*/
|
2007-02-10 17:42:53 +08:00
|
|
|
static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
|
2006-09-27 16:50:08 +08:00
|
|
|
{
|
2007-02-10 17:42:53 +08:00
|
|
|
struct zonelist *zonelist;
|
|
|
|
gfp_t local_flags;
|
2008-04-28 17:12:17 +08:00
|
|
|
struct zoneref *z;
|
2008-04-28 17:12:16 +08:00
|
|
|
struct zone *zone;
|
|
|
|
enum zone_type high_zoneidx = gfp_zone(flags);
|
2006-09-27 16:50:08 +08:00
|
|
|
void *obj = NULL;
|
2006-12-07 12:33:29 +08:00
|
|
|
int nid;
|
2007-02-10 17:42:53 +08:00
|
|
|
|
|
|
|
if (flags & __GFP_THISNODE)
|
|
|
|
return NULL;
|
|
|
|
|
2010-05-25 05:32:08 +08:00
|
|
|
get_mems_allowed();
|
2008-04-28 17:12:14 +08:00
|
|
|
zonelist = node_zonelist(slab_node(current->mempolicy), flags);
|
2007-10-16 16:25:41 +08:00
|
|
|
local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
|
2006-09-27 16:50:08 +08:00
|
|
|
|
2006-12-07 12:33:29 +08:00
|
|
|
retry:
|
|
|
|
/*
|
|
|
|
* Look through allowed nodes for objects available
|
|
|
|
* from existing per node queues.
|
|
|
|
*/
|
2008-04-28 17:12:16 +08:00
|
|
|
for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
|
|
|
|
nid = zone_to_nid(zone);
|
2006-10-22 01:24:16 +08:00
|
|
|
|
2008-04-28 17:12:16 +08:00
|
|
|
if (cpuset_zone_allowed_hardwall(zone, flags) &&
|
2006-12-07 12:33:29 +08:00
|
|
|
cache->nodelists[nid] &&
|
2008-06-22 07:46:35 +08:00
|
|
|
cache->nodelists[nid]->free_objects) {
|
2006-12-07 12:33:29 +08:00
|
|
|
obj = ____cache_alloc_node(cache,
|
|
|
|
flags | GFP_THISNODE, nid);
|
2008-06-22 07:46:35 +08:00
|
|
|
if (obj)
|
|
|
|
break;
|
|
|
|
}
|
2006-12-07 12:33:29 +08:00
|
|
|
}
|
|
|
|
|
2007-05-07 05:50:17 +08:00
|
|
|
if (!obj) {
|
2006-12-07 12:33:29 +08: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 16:34:11 +08: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-27 05:45:03 +08:00
|
|
|
obj = kmem_getpages(cache, local_flags, numa_mem_id());
|
2006-12-13 16:34:11 +08:00
|
|
|
if (local_flags & __GFP_WAIT)
|
|
|
|
local_irq_disable();
|
2006-12-07 12:33:29 +08: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 08:36:36 +08:00
|
|
|
/* cache_grow already freed obj */
|
2006-12-07 12:33:29 +08:00
|
|
|
obj = NULL;
|
|
|
|
}
|
|
|
|
}
|
2006-10-22 01:24:16 +08:00
|
|
|
}
|
2010-05-25 05:32:08 +08:00
|
|
|
put_mems_allowed();
|
2006-09-27 16:50:08 +08:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
|
|
|
* A interface to enable slab creation on nodeid
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2006-12-07 12:32:30 +08:00
|
|
|
static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
|
2006-03-22 16:08:11 +08:00
|
|
|
int nodeid)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
struct list_head *entry;
|
2006-01-08 17:00:37 +08:00
|
|
|
struct slab *slabp;
|
|
|
|
struct kmem_list3 *l3;
|
|
|
|
void *obj;
|
|
|
|
int x;
|
|
|
|
|
|
|
|
l3 = cachep->nodelists[nodeid];
|
|
|
|
BUG_ON(!l3);
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
retry:
|
2006-02-05 15:27:58 +08:00
|
|
|
check_irq_off();
|
2006-01-08 17:00:37 +08: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 19:05:47 +08:00
|
|
|
obj = slab_get_obj(cachep, slabp, nodeid);
|
2006-01-08 17:00:37 +08:00
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
l3->free_objects--;
|
|
|
|
/* move slabp to correct slabp list: */
|
|
|
|
list_del(&slabp->list);
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
if (slabp->free == BUFCTL_END)
|
2006-01-08 17:00:37 +08:00
|
|
|
list_add(&slabp->list, &l3->slabs_full);
|
2006-03-22 16:08:11 +08:00
|
|
|
else
|
2006-01-08 17:00:37 +08:00
|
|
|
list_add(&slabp->list, &l3->slabs_partial);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
spin_unlock(&l3->list_lock);
|
|
|
|
goto done;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
must_grow:
|
2006-01-08 17:00:37 +08:00
|
|
|
spin_unlock(&l3->list_lock);
|
2006-12-07 12:33:29 +08:00
|
|
|
x = cache_grow(cachep, flags | GFP_THISNODE, nodeid, NULL);
|
2006-09-27 16:50:08 +08:00
|
|
|
if (x)
|
|
|
|
goto retry;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-02-10 17:42:53 +08:00
|
|
|
return fallback_alloc(cachep, flags);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
done:
|
2006-01-08 17:00:37 +08:00
|
|
|
return obj;
|
2005-09-10 04:03:32 +08:00
|
|
|
}
|
2007-02-10 17:42:53 +08: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 *
|
|
|
|
__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
|
|
|
|
void *caller)
|
|
|
|
{
|
|
|
|
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-27 05:45:03 +08:00
|
|
|
int slab_node = numa_mem_id();
|
2007-02-10 17:42:53 +08:00
|
|
|
|
2009-06-18 11:24:12 +08:00
|
|
|
flags &= gfp_allowed_mask;
|
2009-06-12 19:03:06 +08: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 15:12:39 +08:00
|
|
|
lockdep_trace_alloc(flags);
|
|
|
|
|
2008-12-23 18:37:01 +08:00
|
|
|
if (slab_should_failslab(cachep, flags))
|
2007-05-07 05:49:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
2007-02-10 17:42:53 +08:00
|
|
|
cache_alloc_debugcheck_before(cachep, flags);
|
|
|
|
local_irq_save(save_flags);
|
|
|
|
|
2011-07-29 04:59:49 +08: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-27 05:45:03 +08:00
|
|
|
nodeid = slab_node;
|
2007-02-10 17:42:53 +08: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-27 05:45:03 +08:00
|
|
|
if (nodeid == slab_node) {
|
2007-02-10 17:42:53 +08: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);
|
2009-06-11 20:22:40 +08:00
|
|
|
kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags,
|
|
|
|
flags);
|
2007-02-10 17:42:53 +08:00
|
|
|
|
2008-05-10 02:35:53 +08:00
|
|
|
if (likely(ptr))
|
|
|
|
kmemcheck_slab_alloc(cachep, flags, ptr, obj_size(cachep));
|
|
|
|
|
2007-07-17 19:03:23 +08:00
|
|
|
if (unlikely((flags & __GFP_ZERO) && ptr))
|
|
|
|
memset(ptr, 0, obj_size(cachep));
|
|
|
|
|
2007-02-10 17:42:53 +08: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-27 05:45:03 +08:00
|
|
|
if (!objp)
|
|
|
|
objp = ____cache_alloc_node(cache, flags, numa_mem_id());
|
2007-02-10 17:42:53 +08: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 *
|
|
|
|
__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
|
|
|
|
{
|
|
|
|
unsigned long save_flags;
|
|
|
|
void *objp;
|
|
|
|
|
2009-06-18 11:24:12 +08:00
|
|
|
flags &= gfp_allowed_mask;
|
2009-06-12 19:03:06 +08: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 15:12:39 +08:00
|
|
|
lockdep_trace_alloc(flags);
|
|
|
|
|
2008-12-23 18:37:01 +08:00
|
|
|
if (slab_should_failslab(cachep, flags))
|
2007-05-07 05:49:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
2007-02-10 17:42:53 +08: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);
|
2009-06-11 20:22:40 +08:00
|
|
|
kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags,
|
|
|
|
flags);
|
2007-02-10 17:42:53 +08:00
|
|
|
prefetchw(objp);
|
|
|
|
|
2008-05-10 02:35:53 +08:00
|
|
|
if (likely(objp))
|
|
|
|
kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep));
|
|
|
|
|
2007-07-17 19:03:23 +08:00
|
|
|
if (unlikely((flags & __GFP_ZERO) && objp))
|
|
|
|
memset(objp, 0, obj_size(cachep));
|
|
|
|
|
2007-02-10 17:42:53 +08:00
|
|
|
return objp;
|
|
|
|
}
|
2005-09-10 04:03:32 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Caller needs to acquire correct kmem_list's list_lock
|
|
|
|
*/
|
2006-02-01 19:05:50 +08:00
|
|
|
static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects,
|
2006-01-08 17:00:37 +08:00
|
|
|
int node)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int i;
|
2005-09-10 04:03:32 +08:00
|
|
|
struct kmem_list3 *l3;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
for (i = 0; i < nr_objects; i++) {
|
|
|
|
void *objp = objpp[i];
|
|
|
|
struct slab *slabp;
|
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
slabp = virt_to_slab(objp);
|
2005-09-23 12:44:02 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
2005-04-17 06:20:36 +08:00
|
|
|
list_del(&slabp->list);
|
2005-09-23 12:44:02 +08:00
|
|
|
check_spinlock_acquired_node(cachep, node);
|
2005-04-17 06:20:36 +08:00
|
|
|
check_slabp(cachep, slabp);
|
2006-02-01 19:05:47 +08:00
|
|
|
slab_put_obj(cachep, slabp, objp, node);
|
2005-04-17 06:20:36 +08:00
|
|
|
STATS_DEC_ACTIVE(cachep);
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->free_objects++;
|
2005-04-17 06:20:36 +08:00
|
|
|
check_slabp(cachep, slabp);
|
|
|
|
|
|
|
|
/* fixup slab chains */
|
|
|
|
if (slabp->inuse == 0) {
|
2005-09-10 04:03:32 +08:00
|
|
|
if (l3->free_objects > l3->free_limit) {
|
|
|
|
l3->free_objects -= cachep->num;
|
2006-09-26 14:31:34 +08: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-17 06:20:36 +08:00
|
|
|
slab_destroy(cachep, slabp);
|
|
|
|
} else {
|
2005-09-10 04:03:32 +08:00
|
|
|
list_add(&slabp->list, &l3->slabs_free);
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
list_add_tail(&slabp->list, &l3->slabs_partial);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int batchcount;
|
2005-09-10 04:03:32 +08: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-27 05:45:03 +08:00
|
|
|
int node = numa_mem_id();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
batchcount = ac->batchcount;
|
|
|
|
#if DEBUG
|
|
|
|
BUG_ON(!batchcount || batchcount > ac->avail);
|
|
|
|
#endif
|
|
|
|
check_irq_off();
|
2005-09-23 12:44:02 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
2006-07-13 20:44:38 +08:00
|
|
|
spin_lock(&l3->list_lock);
|
2005-09-10 04:03:32 +08:00
|
|
|
if (l3->shared) {
|
|
|
|
struct array_cache *shared_array = l3->shared;
|
2006-01-08 17:00:37 +08:00
|
|
|
int max = shared_array->limit - shared_array->avail;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (max) {
|
|
|
|
if (batchcount > max)
|
|
|
|
batchcount = max;
|
2005-09-10 04:03:32 +08:00
|
|
|
memcpy(&(shared_array->entry[shared_array->avail]),
|
2006-01-08 17:00:37 +08:00
|
|
|
ac->entry, sizeof(void *) * batchcount);
|
2005-04-17 06:20:36 +08:00
|
|
|
shared_array->avail += batchcount;
|
|
|
|
goto free_done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-23 12:44:02 +08:00
|
|
|
free_block(cachep, ac->entry, batchcount, node);
|
2006-03-22 16:08:11 +08:00
|
|
|
free_done:
|
2005-04-17 06:20:36 +08:00
|
|
|
#if STATS
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
struct list_head *p;
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
p = l3->slabs_free.next;
|
|
|
|
while (p != &(l3->slabs_free)) {
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
spin_unlock(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
ac->avail -= batchcount;
|
2006-03-22 16:08:11 +08:00
|
|
|
memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-03-22 16:08:11 +08: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-17 06:20:36 +08:00
|
|
|
*/
|
2011-06-02 15:16:42 +08:00
|
|
|
static inline void __cache_free(struct kmem_cache *cachep, void *objp,
|
|
|
|
void *caller)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:49 +08:00
|
|
|
struct array_cache *ac = cpu_cache_get(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
check_irq_off();
|
2009-06-11 20:22:40 +08:00
|
|
|
kmemleak_free_recursive(objp, cachep->flags);
|
2011-06-02 15:16:42 +08:00
|
|
|
objp = cache_free_debugcheck(cachep, objp, caller);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-05-10 02:35:53 +08:00
|
|
|
kmemcheck_slab_free(cachep, objp, obj_size(cachep));
|
|
|
|
|
2007-08-23 05:01:49 +08: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-17 06:32:16 +08:00
|
|
|
if (nr_online_nodes > 1 && cache_free_alien(cachep, objp))
|
2006-06-23 17:03:05 +08:00
|
|
|
return;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (likely(ac->avail < ac->limit)) {
|
|
|
|
STATS_INC_FREEHIT(cachep);
|
2005-09-10 04:03:32 +08:00
|
|
|
ac->entry[ac->avail++] = objp;
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
STATS_INC_FREEMISS(cachep);
|
|
|
|
cache_flusharray(cachep, ac);
|
2005-09-10 04:03:32 +08:00
|
|
|
ac->entry[ac->avail++] = objp;
|
2005-04-17 06:20:36 +08: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 19:05:50 +08:00
|
|
|
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2008-08-11 01:14:05 +08:00
|
|
|
void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0));
|
|
|
|
|
2009-03-23 21:12:24 +08:00
|
|
|
trace_kmem_cache_alloc(_RET_IP_, ret,
|
|
|
|
obj_size(cachep), cachep->buffer_size, flags);
|
2008-08-11 01:14:05 +08:00
|
|
|
|
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc);
|
|
|
|
|
2009-12-11 15:45:30 +08:00
|
|
|
#ifdef CONFIG_TRACING
|
2010-11-25 05:23:34 +08:00
|
|
|
void *
|
|
|
|
kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags)
|
2008-08-11 01:14:05 +08:00
|
|
|
{
|
2010-11-25 05:23:34 +08:00
|
|
|
void *ret;
|
|
|
|
|
|
|
|
ret = __cache_alloc(cachep, flags, __builtin_return_address(0));
|
|
|
|
|
|
|
|
trace_kmalloc(_RET_IP_, ret,
|
|
|
|
size, slab_buffer_size(cachep), flags);
|
|
|
|
return ret;
|
2008-08-11 01:14:05 +08:00
|
|
|
}
|
2010-11-25 05:23:34 +08:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_trace);
|
2008-08-11 01:14:05 +08:00
|
|
|
#endif
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#ifdef CONFIG_NUMA
|
2006-12-07 12:32:30 +08:00
|
|
|
void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
|
|
|
|
{
|
2008-08-11 01:14:05 +08:00
|
|
|
void *ret = __cache_alloc_node(cachep, flags, nodeid,
|
|
|
|
__builtin_return_address(0));
|
|
|
|
|
2009-03-23 21:12:24 +08:00
|
|
|
trace_kmem_cache_alloc_node(_RET_IP_, ret,
|
|
|
|
obj_size(cachep), cachep->buffer_size,
|
|
|
|
flags, nodeid);
|
2008-08-11 01:14:05 +08:00
|
|
|
|
|
|
|
return ret;
|
2006-12-07 12:32:30 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_node);
|
|
|
|
|
2009-12-11 15:45:30 +08:00
|
|
|
#ifdef CONFIG_TRACING
|
2010-11-25 05:23:34 +08:00
|
|
|
void *kmem_cache_alloc_node_trace(size_t size,
|
|
|
|
struct kmem_cache *cachep,
|
|
|
|
gfp_t flags,
|
|
|
|
int nodeid)
|
2008-08-11 01:14:05 +08:00
|
|
|
{
|
2010-11-25 05:23:34 +08:00
|
|
|
void *ret;
|
|
|
|
|
|
|
|
ret = __cache_alloc_node(cachep, flags, nodeid,
|
2008-08-11 01:14:05 +08:00
|
|
|
__builtin_return_address(0));
|
2010-11-25 05:23:34 +08:00
|
|
|
trace_kmalloc_node(_RET_IP_, ret,
|
|
|
|
size, slab_buffer_size(cachep),
|
|
|
|
flags, nodeid);
|
|
|
|
return ret;
|
2008-08-11 01:14:05 +08:00
|
|
|
}
|
2010-11-25 05:23:34 +08:00
|
|
|
EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
|
2008-08-11 01:14:05 +08:00
|
|
|
#endif
|
|
|
|
|
2006-12-07 12:32:30 +08:00
|
|
|
static __always_inline void *
|
|
|
|
__do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller)
|
2005-05-01 23:58:38 +08:00
|
|
|
{
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep;
|
2005-05-01 23:58:38 +08:00
|
|
|
|
|
|
|
cachep = kmem_find_general_cachep(size, flags);
|
2007-07-17 19:03:22 +08:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(cachep)))
|
|
|
|
return cachep;
|
2010-11-25 05:23:34 +08:00
|
|
|
return kmem_cache_alloc_node_trace(size, cachep, flags, node);
|
2005-05-01 23:58:38 +08:00
|
|
|
}
|
2006-12-07 12:32:30 +08:00
|
|
|
|
2009-12-11 15:45:50 +08:00
|
|
|
#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
|
2006-12-07 12:32:30 +08:00
|
|
|
void *__kmalloc_node(size_t size, gfp_t flags, int node)
|
|
|
|
{
|
|
|
|
return __do_kmalloc_node(size, flags, node,
|
|
|
|
__builtin_return_address(0));
|
|
|
|
}
|
2006-09-26 14:31:36 +08:00
|
|
|
EXPORT_SYMBOL(__kmalloc_node);
|
2006-12-07 12:32:30 +08:00
|
|
|
|
|
|
|
void *__kmalloc_node_track_caller(size_t size, gfp_t flags,
|
2008-08-20 01:43:25 +08:00
|
|
|
int node, unsigned long caller)
|
2006-12-07 12:32:30 +08:00
|
|
|
{
|
2008-08-20 01:43:25 +08:00
|
|
|
return __do_kmalloc_node(size, flags, node, (void *)caller);
|
2006-12-07 12:32:30 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_node_track_caller);
|
|
|
|
#else
|
|
|
|
void *__kmalloc_node(size_t size, gfp_t flags, int node)
|
|
|
|
{
|
|
|
|
return __do_kmalloc_node(size, flags, node, NULL);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_node);
|
2009-12-11 15:45:50 +08:00
|
|
|
#endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */
|
2006-12-07 12:32:30 +08:00
|
|
|
#endif /* CONFIG_NUMA */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/**
|
2006-06-23 17:03:48 +08:00
|
|
|
* __do_kmalloc - allocate memory
|
2005-04-17 06:20:36 +08:00
|
|
|
* @size: how many bytes of memory are required.
|
2006-06-23 17:03:48 +08:00
|
|
|
* @flags: the type of memory to allocate (see kmalloc).
|
2006-03-22 16:08:14 +08:00
|
|
|
* @caller: function caller for debug tracking of the caller
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2006-02-01 19:05:52 +08:00
|
|
|
static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
|
|
|
|
void *caller)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep;
|
2008-08-11 01:14:05 +08:00
|
|
|
void *ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-05-01 23:58:38 +08: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-20 04:17:15 +08:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(cachep)))
|
|
|
|
return cachep;
|
2008-08-11 01:14:05 +08:00
|
|
|
ret = __cache_alloc(cachep, flags, caller);
|
|
|
|
|
2009-03-23 21:12:24 +08:00
|
|
|
trace_kmalloc((unsigned long) caller, ret,
|
|
|
|
size, cachep->buffer_size, flags);
|
2008-08-11 01:14:05 +08:00
|
|
|
|
|
|
|
return ret;
|
2006-02-01 19:05:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-11 15:45:50 +08:00
|
|
|
#if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
|
2006-02-01 19:05:52 +08:00
|
|
|
void *__kmalloc(size_t size, gfp_t flags)
|
|
|
|
{
|
2006-03-25 19:06:39 +08:00
|
|
|
return __do_kmalloc(size, flags, __builtin_return_address(0));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc);
|
|
|
|
|
2008-08-20 01:43:25 +08:00
|
|
|
void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
|
2006-02-01 19:05:52 +08:00
|
|
|
{
|
2008-08-20 01:43:25 +08:00
|
|
|
return __do_kmalloc(size, flags, (void *)caller);
|
2006-02-01 19:05:52 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc_track_caller);
|
2006-10-04 17:15:25 +08:00
|
|
|
|
|
|
|
#else
|
|
|
|
void *__kmalloc(size_t size, gfp_t flags)
|
|
|
|
{
|
|
|
|
return __do_kmalloc(size, flags, NULL);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__kmalloc);
|
2006-02-01 19:05:52 +08:00
|
|
|
#endif
|
|
|
|
|
2005-04-17 06:20:36 +08: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 19:05:50 +08:00
|
|
|
void kmem_cache_free(struct kmem_cache *cachep, void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
local_irq_save(flags);
|
2007-02-10 17:44:57 +08:00
|
|
|
debug_check_no_locks_freed(objp, obj_size(cachep));
|
2008-04-30 15:55:01 +08:00
|
|
|
if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
|
|
|
|
debug_check_no_obj_freed(objp, obj_size(cachep));
|
2011-06-02 15:16:42 +08:00
|
|
|
__cache_free(cachep, objp, __builtin_return_address(0));
|
2005-04-17 06:20:36 +08:00
|
|
|
local_irq_restore(flags);
|
2008-08-11 01:14:05 +08:00
|
|
|
|
2009-03-23 21:12:24 +08:00
|
|
|
trace_kmem_cache_free(_RET_IP_, objp);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_free);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* kfree - free previously allocated memory
|
|
|
|
* @objp: pointer returned by kmalloc.
|
|
|
|
*
|
2005-09-10 04:10:16 +08:00
|
|
|
* If @objp is NULL, no operation is performed.
|
|
|
|
*
|
2005-04-17 06:20:36 +08:00
|
|
|
* Don't free memory not originally allocated by kmalloc()
|
|
|
|
* or you will run into trouble.
|
|
|
|
*/
|
|
|
|
void kfree(const void *objp)
|
|
|
|
{
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *c;
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned long flags;
|
|
|
|
|
2009-03-25 17:05:57 +08:00
|
|
|
trace_kfree(_RET_IP_, objp);
|
|
|
|
|
2007-07-17 19:03:22 +08:00
|
|
|
if (unlikely(ZERO_OR_NULL_PTR(objp)))
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
local_irq_save(flags);
|
|
|
|
kfree_debugcheck(objp);
|
2006-02-01 19:05:49 +08:00
|
|
|
c = virt_to_cache(objp);
|
2006-06-27 17:54:49 +08:00
|
|
|
debug_check_no_locks_freed(objp, obj_size(c));
|
2008-04-30 15:55:01 +08:00
|
|
|
debug_check_no_obj_freed(objp, obj_size(c));
|
2011-06-02 15:16:42 +08:00
|
|
|
__cache_free(c, (void *)objp, __builtin_return_address(0));
|
2005-04-17 06:20:36 +08:00
|
|
|
local_irq_restore(flags);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kfree);
|
|
|
|
|
2006-02-01 19:05:50 +08:00
|
|
|
unsigned int kmem_cache_size(struct kmem_cache *cachep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-02-01 19:05:42 +08:00
|
|
|
return obj_size(cachep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kmem_cache_size);
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
/*
|
2007-10-20 07:27:18 +08:00
|
|
|
* This initializes kmem_list3 or resizes various caches for all nodes.
|
2005-09-10 04:03:32 +08:00
|
|
|
*/
|
2009-06-11 00:40:04 +08:00
|
|
|
static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp)
|
2005-09-10 04:03:32 +08:00
|
|
|
{
|
|
|
|
int node;
|
|
|
|
struct kmem_list3 *l3;
|
2006-03-25 19:06:46 +08:00
|
|
|
struct array_cache *new_shared;
|
2006-12-07 12:32:16 +08:00
|
|
|
struct array_cache **new_alien = NULL;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2008-01-24 21:49:54 +08:00
|
|
|
for_each_online_node(node) {
|
2006-03-25 19:06:46 +08:00
|
|
|
|
2006-12-07 12:32:16 +08:00
|
|
|
if (use_alien_caches) {
|
2009-06-11 00:40:04 +08:00
|
|
|
new_alien = alloc_alien_cache(node, cachep->limit, gfp);
|
2006-12-07 12:32:16 +08:00
|
|
|
if (!new_alien)
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 19:06:46 +08:00
|
|
|
|
2007-05-07 05:49:28 +08:00
|
|
|
new_shared = NULL;
|
|
|
|
if (cachep->shared) {
|
|
|
|
new_shared = alloc_arraycache(node,
|
2006-03-25 19:06:47 +08:00
|
|
|
cachep->shared*cachep->batchcount,
|
2009-06-11 00:40:04 +08:00
|
|
|
0xbaadf00d, gfp);
|
2007-05-07 05:49:28 +08:00
|
|
|
if (!new_shared) {
|
|
|
|
free_alien_cache(new_alien);
|
|
|
|
goto fail;
|
|
|
|
}
|
2006-03-25 19:06:47 +08:00
|
|
|
}
|
2006-03-25 19:06:46 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (l3) {
|
2006-03-25 19:06:46 +08:00
|
|
|
struct array_cache *shared = l3->shared;
|
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
|
|
|
|
2006-03-25 19:06:46 +08:00
|
|
|
if (shared)
|
2006-03-25 19:06:47 +08:00
|
|
|
free_block(cachep, shared->entry,
|
|
|
|
shared->avail, node);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-03-25 19:06:46 +08:00
|
|
|
l3->shared = new_shared;
|
|
|
|
if (!l3->alien) {
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->alien = new_alien;
|
|
|
|
new_alien = NULL;
|
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
l3->free_limit = (1 + nr_cpus_node(node)) *
|
2006-03-22 16:08:11 +08:00
|
|
|
cachep->batchcount + cachep->num;
|
2005-09-10 04:03:32 +08:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2006-03-25 19:06:46 +08:00
|
|
|
kfree(shared);
|
2005-09-10 04:03:32 +08:00
|
|
|
free_alien_cache(new_alien);
|
|
|
|
continue;
|
|
|
|
}
|
2009-06-11 00:40:04 +08:00
|
|
|
l3 = kmalloc_node(sizeof(struct kmem_list3), gfp, node);
|
2006-03-25 19:06:47 +08:00
|
|
|
if (!l3) {
|
|
|
|
free_alien_cache(new_alien);
|
|
|
|
kfree(new_shared);
|
2005-09-10 04:03:32 +08:00
|
|
|
goto fail;
|
2006-03-25 19:06:47 +08:00
|
|
|
}
|
2005-09-10 04:03:32 +08:00
|
|
|
|
|
|
|
kmem_list3_init(l3);
|
|
|
|
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
|
2006-03-22 16:08:11 +08:00
|
|
|
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
|
2006-03-25 19:06:46 +08:00
|
|
|
l3->shared = new_shared;
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->alien = new_alien;
|
2006-01-08 17:00:37 +08:00
|
|
|
l3->free_limit = (1 + nr_cpus_node(node)) *
|
2006-03-22 16:08:11 +08:00
|
|
|
cachep->batchcount + cachep->num;
|
2005-09-10 04:03:32 +08:00
|
|
|
cachep->nodelists[node] = l3;
|
|
|
|
}
|
2006-03-25 19:06:46 +08:00
|
|
|
return 0;
|
2006-03-25 19:06:47 +08:00
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
fail:
|
2006-03-25 19:06:47 +08:00
|
|
|
if (!cachep->next.next) {
|
|
|
|
/* 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 19:06:46 +08:00
|
|
|
return -ENOMEM;
|
2005-09-10 04:03:32 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
struct ccupdate_struct {
|
2006-02-01 19:05:50 +08:00
|
|
|
struct kmem_cache *cachep;
|
2011-07-25 14:55:42 +08:00
|
|
|
struct array_cache *new[0];
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static void do_ccupdate_local(void *info)
|
|
|
|
{
|
2006-03-22 16:08:11 +08:00
|
|
|
struct ccupdate_struct *new = info;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct array_cache *old;
|
|
|
|
|
|
|
|
check_irq_off();
|
2006-02-01 19:05:49 +08:00
|
|
|
old = cpu_cache_get(new->cachep);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
|
|
|
|
new->new[smp_processor_id()] = old;
|
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:12 +08:00
|
|
|
/* Always called with the cache_chain_mutex held */
|
2006-03-22 16:08:11 +08:00
|
|
|
static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
|
2009-06-11 00:40:04 +08:00
|
|
|
int batchcount, int shared, gfp_t gfp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-09-26 14:31:47 +08:00
|
|
|
struct ccupdate_struct *new;
|
2006-09-26 14:31:38 +08:00
|
|
|
int i;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-25 14:55:42 +08:00
|
|
|
new = kzalloc(sizeof(*new) + nr_cpu_ids * sizeof(struct array_cache *),
|
|
|
|
gfp);
|
2006-09-26 14:31:47 +08:00
|
|
|
if (!new)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2005-09-10 04:03:32 +08: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-27 05:45:03 +08:00
|
|
|
new->new[i] = alloc_arraycache(cpu_to_mem(i), limit,
|
2009-06-11 00:40:04 +08:00
|
|
|
batchcount, gfp);
|
2006-09-26 14:31:47 +08:00
|
|
|
if (!new->new[i]) {
|
2006-01-08 17:00:37 +08:00
|
|
|
for (i--; i >= 0; i--)
|
2006-09-26 14:31:47 +08:00
|
|
|
kfree(new->new[i]);
|
|
|
|
kfree(new);
|
2005-09-10 04:03:32 +08:00
|
|
|
return -ENOMEM;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2006-09-26 14:31:47 +08:00
|
|
|
new->cachep = cachep;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-05-09 15:39:44 +08:00
|
|
|
on_each_cpu(do_ccupdate_local, (void *)new, 1);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
check_irq_on();
|
|
|
|
cachep->batchcount = batchcount;
|
|
|
|
cachep->limit = limit;
|
2005-09-10 04:03:32 +08:00
|
|
|
cachep->shared = shared;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
for_each_online_cpu(i) {
|
2006-09-26 14:31:47 +08:00
|
|
|
struct array_cache *ccold = new->new[i];
|
2005-04-17 06:20:36 +08: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-27 05:45:03 +08: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-17 06:20:36 +08:00
|
|
|
kfree(ccold);
|
|
|
|
}
|
2006-09-26 14:31:47 +08:00
|
|
|
kfree(new);
|
2009-06-11 00:40:04 +08:00
|
|
|
return alloc_kmemlist(cachep, gfp);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:08:12 +08:00
|
|
|
/* Called with cache_chain_mutex held always */
|
2009-06-11 00:40:04 +08:00
|
|
|
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
int limit, shared;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* The head array serves three purposes:
|
2005-04-17 06:20:36 +08:00
|
|
|
* - create a LIFO ordering, i.e. return objects that are cache-warm
|
|
|
|
* - reduce the number of spinlock operations.
|
2006-03-22 16:08:11 +08:00
|
|
|
* - reduce the number of linked list operations on the slab and
|
2005-04-17 06:20:36 +08:00
|
|
|
* bufctl chains: array operations are cheaper.
|
|
|
|
* The numbers are guessed, we should auto-tune as described by
|
|
|
|
* Bonwick.
|
|
|
|
*/
|
2006-02-01 19:05:42 +08:00
|
|
|
if (cachep->buffer_size > 131072)
|
2005-04-17 06:20:36 +08:00
|
|
|
limit = 1;
|
2006-02-01 19:05:42 +08:00
|
|
|
else if (cachep->buffer_size > PAGE_SIZE)
|
2005-04-17 06:20:36 +08:00
|
|
|
limit = 8;
|
2006-02-01 19:05:42 +08:00
|
|
|
else if (cachep->buffer_size > 1024)
|
2005-04-17 06:20:36 +08:00
|
|
|
limit = 24;
|
2006-02-01 19:05:42 +08:00
|
|
|
else if (cachep->buffer_size > 256)
|
2005-04-17 06:20:36 +08:00
|
|
|
limit = 54;
|
|
|
|
else
|
|
|
|
limit = 120;
|
|
|
|
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* CPU bound tasks (e.g. network routing) can exhibit cpu bound
|
2005-04-17 06:20:36 +08: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;
|
2007-05-07 05:49:27 +08:00
|
|
|
if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1)
|
2005-04-17 06:20:36 +08:00
|
|
|
shared = 8;
|
|
|
|
|
|
|
|
#if DEBUG
|
2006-03-22 16:08:11 +08:00
|
|
|
/*
|
|
|
|
* With debugging enabled, large batchcount lead to excessively long
|
|
|
|
* periods with disabled local interrupts. Limit the batchcount
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
if (limit > 32)
|
|
|
|
limit = 32;
|
|
|
|
#endif
|
2009-06-11 00:40:04 +08:00
|
|
|
err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared, gfp);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (err)
|
|
|
|
printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
|
2006-01-08 17:00:37 +08:00
|
|
|
cachep->name, -err);
|
2006-09-26 14:31:38 +08:00
|
|
|
return err;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-22 16:09:07 +08:00
|
|
|
/*
|
|
|
|
* Drain an array if it contains any elements taking the l3 lock only if
|
2006-03-22 16:09:07 +08:00
|
|
|
* necessary. Note that the l3 listlock also protects the array_cache
|
|
|
|
* if drain_array() is used on the shared array.
|
2006-03-22 16:09:07 +08:00
|
|
|
*/
|
2011-01-12 07:49:32 +08:00
|
|
|
static void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,
|
2006-03-22 16:09:07 +08:00
|
|
|
struct array_cache *ac, int force, int node)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int tofree;
|
|
|
|
|
2006-03-22 16:09:07 +08:00
|
|
|
if (!ac || !ac->avail)
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ac->touched && !force) {
|
|
|
|
ac->touched = 0;
|
2006-03-22 16:09:07 +08:00
|
|
|
} else {
|
2006-03-22 16:09:07 +08:00
|
|
|
spin_lock_irq(&l3->list_lock);
|
2006-03-22 16:09:07 +08: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 16:09:07 +08:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* cache_reap - Reclaim memory from caches.
|
2007-03-01 12:12:13 +08:00
|
|
|
* @w: work descriptor
|
2005-04-17 06:20:36 +08: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 16:08:11 +08:00
|
|
|
* If we cannot acquire the cache chain mutex then just give up - we'll try
|
|
|
|
* again on the next iteration.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-02-10 17:42:55 +08:00
|
|
|
static void cache_reap(struct work_struct *w)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-06-23 17:03:17 +08:00
|
|
|
struct kmem_cache *searchp;
|
2005-09-10 04:03:32 +08: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-27 05:45:03 +08:00
|
|
|
int node = numa_mem_id();
|
2009-04-03 07:56:54 +08:00
|
|
|
struct delayed_work *work = to_delayed_work(w);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-02-10 17:42:55 +08:00
|
|
|
if (!mutex_trylock(&cache_chain_mutex))
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Give up. Setup the next iteration. */
|
2007-02-10 17:42:55 +08:00
|
|
|
goto out;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(searchp, &cache_chain, next) {
|
2005-04-17 06:20:36 +08:00
|
|
|
check_irq_on();
|
|
|
|
|
2006-03-22 16:09:05 +08: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 16:09:06 +08:00
|
|
|
l3 = searchp->nodelists[node];
|
2006-03-22 16:09:05 +08:00
|
|
|
|
2006-03-10 09:33:54 +08:00
|
|
|
reap_alien(searchp, l3);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:09:06 +08:00
|
|
|
drain_array(searchp, l3, cpu_cache_get(searchp), 0, node);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:09:05 +08:00
|
|
|
/*
|
|
|
|
* These are racy checks but it does not matter
|
|
|
|
* if we skip one check or scan twice.
|
|
|
|
*/
|
2005-09-10 04:03:32 +08:00
|
|
|
if (time_after(l3->next_reap, jiffies))
|
2006-03-22 16:09:05 +08:00
|
|
|
goto next;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->next_reap = jiffies + REAPTIMEOUT_LIST3;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-03-22 16:09:06 +08:00
|
|
|
drain_array(searchp, l3, l3->shared, 0, node);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-30 16:55:45 +08:00
|
|
|
if (l3->free_touched)
|
2005-09-10 04:03:32 +08:00
|
|
|
l3->free_touched = 0;
|
2006-06-30 16:55:45 +08:00
|
|
|
else {
|
|
|
|
int freed;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-30 16:55:45 +08:00
|
|
|
freed = drain_freelist(searchp, l3, (l3->free_limit +
|
|
|
|
5 * searchp->num - 1) / (5 * searchp->num));
|
|
|
|
STATS_ADD_REAPED(searchp, freed);
|
|
|
|
}
|
2006-03-22 16:09:05 +08:00
|
|
|
next:
|
2005-04-17 06:20:36 +08:00
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
check_irq_on();
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2006-03-10 09:33:54 +08:00
|
|
|
next_reap_node();
|
2007-02-10 17:42:55 +08:00
|
|
|
out:
|
2006-03-22 16:08:11 +08:00
|
|
|
/* Set up the next iteration */
|
2007-02-10 17:42:55 +08:00
|
|
|
schedule_delayed_work(work, round_jiffies_relative(REAPTIMEOUT_CPUC));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2008-01-03 05:04:48 +08:00
|
|
|
#ifdef CONFIG_SLABINFO
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-01-08 17:00:36 +08:00
|
|
|
static void print_slabinfo_header(struct seq_file *m)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:36 +08:00
|
|
|
/*
|
|
|
|
* Output format version, so at least we can change it
|
|
|
|
* without _too_ many complaints.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
#if STATS
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
#else
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_puts(m, "slabinfo - version: 2.1\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_puts(m, "# name <active_objs> <num_objs> <objsize> "
|
|
|
|
"<objperslab> <pagesperslab>");
|
|
|
|
seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
|
|
|
|
seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
|
2005-04-17 06:20:36 +08:00
|
|
|
#if STATS
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
|
2006-04-11 13:52:54 +08:00
|
|
|
"<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
2006-01-08 17:00:36 +08:00
|
|
|
seq_putc(m, '\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *s_start(struct seq_file *m, loff_t *pos)
|
|
|
|
{
|
|
|
|
loff_t n = *pos;
|
|
|
|
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
2006-01-08 17:00:36 +08:00
|
|
|
if (!n)
|
|
|
|
print_slabinfo_header(m);
|
2007-07-16 14:38:04 +08:00
|
|
|
|
|
|
|
return seq_list_start(&cache_chain, *pos);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *s_next(struct seq_file *m, void *p, loff_t *pos)
|
|
|
|
{
|
2007-07-16 14:38:04 +08:00
|
|
|
return seq_list_next(p, &cache_chain, pos);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void s_stop(struct seq_file *m, void *p)
|
|
|
|
{
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int s_show(struct seq_file *m, void *p)
|
|
|
|
{
|
2007-07-16 14:38:04 +08:00
|
|
|
struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
|
2006-01-08 17:00:37 +08: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-10 04:03:32 +08:00
|
|
|
const char *name;
|
2005-04-17 06:20:36 +08:00
|
|
|
char *error = NULL;
|
2005-09-10 04:03:32 +08:00
|
|
|
int node;
|
|
|
|
struct kmem_list3 *l3;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
active_objs = 0;
|
|
|
|
num_slabs = 0;
|
2005-09-10 04:03:32 +08:00
|
|
|
for_each_online_node(node) {
|
|
|
|
l3 = cachep->nodelists[node];
|
|
|
|
if (!l3)
|
|
|
|
continue;
|
|
|
|
|
2006-02-05 15:27:58 +08:00
|
|
|
check_irq_on();
|
|
|
|
spin_lock_irq(&l3->list_lock);
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list) {
|
2005-09-10 04:03:32 +08:00
|
|
|
if (slabp->inuse != cachep->num && !error)
|
|
|
|
error = "slabs_full accounting error";
|
|
|
|
active_objs += cachep->num;
|
|
|
|
active_slabs++;
|
|
|
|
}
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list) {
|
2005-09-10 04:03:32 +08: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 17:03:17 +08:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_free, list) {
|
2005-09-10 04:03:32 +08: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 15:27:59 +08:00
|
|
|
if (l3->shared)
|
|
|
|
shared_avail += l3->shared->avail;
|
2005-09-10 04:03:32 +08:00
|
|
|
|
2006-02-05 15:27:58 +08:00
|
|
|
spin_unlock_irq(&l3->list_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-01-08 17:00:37 +08:00
|
|
|
num_slabs += active_slabs;
|
|
|
|
num_objs = num_slabs * cachep->num;
|
2005-09-10 04:03:32 +08:00
|
|
|
if (num_objs - active_objs != free_objects && !error)
|
2005-04-17 06:20:36 +08:00
|
|
|
error = "free_objects accounting error";
|
|
|
|
|
2006-01-08 17:00:37 +08:00
|
|
|
name = cachep->name;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (error)
|
|
|
|
printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
|
|
|
|
|
|
|
|
seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
|
2006-02-01 19:05:42 +08:00
|
|
|
name, active_objs, num_objs, cachep->buffer_size,
|
2006-01-08 17:00:37 +08:00
|
|
|
cachep->num, (1 << cachep->gfporder));
|
2005-04-17 06:20:36 +08:00
|
|
|
seq_printf(m, " : tunables %4u %4u %4u",
|
2006-01-08 17:00:37 +08:00
|
|
|
cachep->limit, cachep->batchcount, cachep->shared);
|
2005-09-10 04:03:32 +08:00
|
|
|
seq_printf(m, " : slabdata %6lu %6lu %6lu",
|
2006-01-08 17:00:37 +08:00
|
|
|
active_slabs, num_slabs, shared_avail);
|
2005-04-17 06:20:36 +08:00
|
|
|
#if STATS
|
2006-01-08 17:00:37 +08:00
|
|
|
{ /* list3 stats */
|
2005-04-17 06:20:36 +08: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-10 04:03:32 +08:00
|
|
|
unsigned long node_frees = cachep->node_frees;
|
2006-04-11 13:52:54 +08:00
|
|
|
unsigned long overflows = cachep->node_overflow;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-03-27 10:27:58 +08: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-17 06:20:36 +08: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 17:00:37 +08:00
|
|
|
allochit, allocmiss, freehit, freemiss);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
seq_putc(m, '\n');
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* slabinfo_op - iterator that generates /proc/slabinfo
|
|
|
|
*
|
|
|
|
* Output layout:
|
|
|
|
* cache-name
|
|
|
|
* num-active-objs
|
|
|
|
* total-objs
|
|
|
|
* object size
|
|
|
|
* num-active-slabs
|
|
|
|
* total-slabs
|
|
|
|
* num-pages-per-slab
|
|
|
|
* + further values on SMP and with statistics enabled
|
|
|
|
*/
|
|
|
|
|
2008-10-06 06:42:17 +08:00
|
|
|
static const struct seq_operations slabinfo_op = {
|
2006-01-08 17:00:37 +08:00
|
|
|
.start = s_start,
|
|
|
|
.next = s_next,
|
|
|
|
.stop = s_stop,
|
|
|
|
.show = s_show,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_SLABINFO_WRITE 128
|
|
|
|
/**
|
|
|
|
* slabinfo_write - Tuning for the slab allocator
|
|
|
|
* @file: unused
|
|
|
|
* @buffer: user buffer
|
|
|
|
* @count: data length
|
|
|
|
* @ppos: unused
|
|
|
|
*/
|
2011-01-12 07:49:32 +08:00
|
|
|
static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
|
2006-01-08 17:00:37 +08:00
|
|
|
size_t count, loff_t *ppos)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:00:37 +08:00
|
|
|
char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
|
2005-04-17 06:20:36 +08:00
|
|
|
int limit, batchcount, shared, res;
|
2006-06-23 17:03:17 +08:00
|
|
|
struct kmem_cache *cachep;
|
2006-01-08 17:00:37 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (count > MAX_SLABINFO_WRITE)
|
|
|
|
return -EINVAL;
|
|
|
|
if (copy_from_user(&kbuf, buffer, count))
|
|
|
|
return -EFAULT;
|
2006-01-08 17:00:37 +08:00
|
|
|
kbuf[MAX_SLABINFO_WRITE] = '\0';
|
2005-04-17 06:20:36 +08: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. */
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_lock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
res = -EINVAL;
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(cachep, &cache_chain, next) {
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!strcmp(cachep->name, kbuf)) {
|
2006-03-22 16:08:11 +08:00
|
|
|
if (limit < 1 || batchcount < 1 ||
|
|
|
|
batchcount > limit || shared < 0) {
|
2005-09-10 04:03:32 +08:00
|
|
|
res = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
2005-09-10 04:03:32 +08:00
|
|
|
res = do_tune_cpucache(cachep, limit,
|
2009-06-11 00:40:04 +08:00
|
|
|
batchcount, shared,
|
|
|
|
GFP_KERNEL);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-01-19 09:42:33 +08:00
|
|
|
mutex_unlock(&cache_chain_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (res >= 0)
|
|
|
|
res = count;
|
|
|
|
return res;
|
|
|
|
}
|
2006-03-25 19:06:39 +08:00
|
|
|
|
2008-10-06 06:42:17 +08:00
|
|
|
static int slabinfo_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return seq_open(file, &slabinfo_op);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations proc_slabinfo_operations = {
|
|
|
|
.open = slabinfo_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.write = slabinfo_write,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = seq_release,
|
|
|
|
};
|
|
|
|
|
2006-03-25 19:06:39 +08:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
|
|
|
|
static void *leaks_start(struct seq_file *m, loff_t *pos)
|
|
|
|
{
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
2007-07-16 14:38:04 +08:00
|
|
|
return seq_list_start(&cache_chain, *pos);
|
2006-03-25 19:06:39 +08: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;
|
|
|
|
for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) {
|
|
|
|
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 19:03:51 +08:00
|
|
|
char modname[MODULE_NAME_LEN], name[KSYM_NAME_LEN];
|
2006-03-25 19:06:39 +08:00
|
|
|
|
2007-05-08 15:28:47 +08:00
|
|
|
if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) {
|
2006-03-25 19:06:39 +08:00
|
|
|
seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
|
2007-05-08 15:28:47 +08:00
|
|
|
if (modname[0])
|
2006-03-25 19:06:39 +08:00
|
|
|
seq_printf(m, " [%s]", modname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
seq_printf(m, "%p", (void *)address);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int leaks_show(struct seq_file *m, void *p)
|
|
|
|
{
|
2007-07-16 14:38:04 +08:00
|
|
|
struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);
|
2006-03-25 19:06:39 +08: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 17:03:17 +08:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_full, list)
|
2006-03-25 19:06:39 +08:00
|
|
|
handle_slab(n, cachep, slabp);
|
2006-06-23 17:03:17 +08:00
|
|
|
list_for_each_entry(slabp, &l3->slabs_partial, list)
|
2006-03-25 19:06:39 +08:00
|
|
|
handle_slab(n, cachep, slabp);
|
|
|
|
spin_unlock_irq(&l3->list_lock);
|
|
|
|
}
|
|
|
|
name = cachep->name;
|
|
|
|
if (n[0] == n[1]) {
|
|
|
|
/* Increase the buffer size */
|
|
|
|
mutex_unlock(&cache_chain_mutex);
|
|
|
|
m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
|
|
|
|
if (!m->private) {
|
|
|
|
/* Too bad, we are really out */
|
|
|
|
m->private = n;
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
*(unsigned long *)m->private = n[0] * 2;
|
|
|
|
kfree(n);
|
|
|
|
mutex_lock(&cache_chain_mutex);
|
|
|
|
/* 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 14:31:47 +08:00
|
|
|
|
2006-03-25 19:06:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-06 04:59:10 +08:00
|
|
|
static const struct seq_operations slabstats_op = {
|
2006-03-25 19:06:39 +08:00
|
|
|
.start = leaks_start,
|
|
|
|
.next = s_next,
|
|
|
|
.stop = s_stop,
|
|
|
|
.show = leaks_show,
|
|
|
|
};
|
2008-10-06 04:59:10 +08: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)
|
|
|
|
{
|
mm: restrict access to slab files under procfs and sysfs
Historically /proc/slabinfo and files under /sys/kernel/slab/* have
world read permissions and are accessible to the world. slabinfo
contains rather private information related both to the kernel and
userspace tasks. Depending on the situation, it might reveal either
private information per se or information useful to make another
targeted attack. Some examples of what can be learned by
reading/watching for /proc/slabinfo entries:
1) dentry (and different *inode*) number might reveal other processes fs
activity. The number of dentry "active objects" doesn't strictly show
file count opened/touched by a process, however, there is a good
correlation between them. The patch "proc: force dcache drop on
unauthorized access" relies on the privacy of dentry count.
2) different inode entries might reveal the same information as (1), but
these are more fine granted counters. If a filesystem is mounted in a
private mount point (or even a private namespace) and fs type differs from
other mounted fs types, fs activity in this mount point/namespace is
revealed. If there is a single ecryptfs mount point, the whole fs
activity of a single user is revealed. Number of files in ecryptfs
mount point is a private information per se.
3) fuse_* reveals number of files / fs activity of a user in a user
private mount point. It is approx. the same severity as ecryptfs
infoleak in (2).
4) sysfs_dir_cache similar to (2) reveals devices' addition/removal,
which can be otherwise hidden by "chmod 0700 /sys/". With 0444 slabinfo
the precise number of sysfs files is known to the world.
5) buffer_head might reveal some kernel activity. With other
information leaks an attacker might identify what specific kernel
routines generate buffer_head activity.
6) *kmalloc* infoleaks are very situational. Attacker should watch for
the specific kmalloc size entry and filter the noise related to the unrelated
kernel activity. If an attacker has relatively silent victim system, he
might get rather precise counters.
Additional information sources might significantly increase the slabinfo
infoleak benefits. E.g. if an attacker knows that the processes
activity on the system is very low (only core daemons like syslog and
cron), he may run setxid binaries / trigger local daemon activity /
trigger network services activity / await sporadic cron jobs activity
/ etc. and get rather precise counters for fs and network activity of
these privileged tasks, which is unknown otherwise.
Also hiding slabinfo and /sys/kernel/slab/* is a one step to complicate
exploitation of kernel heap overflows (and possibly, other bugs). The
related discussion:
http://thread.gmane.org/gmane.linux.kernel/1108378
To keep compatibility with old permission model where non-root
monitoring daemon could watch for kernel memleaks though slabinfo one
should do:
groupadd slabinfo
usermod -a -G slabinfo $MONITOR_USER
And add the following commands to init scripts (to mountall.conf in
Ubuntu's upstart case):
chmod g+r /proc/slabinfo /sys/kernel/slab/*/*
chgrp slabinfo /proc/slabinfo /sys/kernel/slab/*/*
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Reviewed-by: Kees Cook <kees@ubuntu.com>
Reviewed-by: Dave Hansen <dave@linux.vnet.ibm.com>
Acked-by: Christoph Lameter <cl@gentwo.org>
Acked-by: David Rientjes <rientjes@google.com>
CC: Valdis.Kletnieks@vt.edu
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Alan Cox <alan@linux.intel.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
2011-09-28 01:54:53 +08:00
|
|
|
proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
|
2008-10-06 04:59:10 +08:00
|
|
|
#ifdef CONFIG_DEBUG_SLAB_LEAK
|
|
|
|
proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
|
2006-03-25 19:06:39 +08:00
|
|
|
#endif
|
2008-10-06 04:59:10 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
module_init(slab_proc_init);
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
|
2005-09-04 06:55:07 +08: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-07 05:48:40 +08:00
|
|
|
size_t ksize(const void *objp)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-10-16 16:24:46 +08:00
|
|
|
BUG_ON(!objp);
|
|
|
|
if (unlikely(objp == ZERO_SIZE_PTR))
|
2005-09-04 06:55:07 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-02-01 19:05:49 +08:00
|
|
|
return obj_size(virt_to_cache(objp));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2009-02-10 21:21:44 +08:00
|
|
|
EXPORT_SYMBOL(ksize);
|