Commit 138c4ae9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'slab/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg/linux

* 'slab/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg/linux:
  tools, slub: Fix off-by-one buffer corruption after readlink() call
  slub: Discard slab page when node partial > minimum partial number
  slub: correct comments error for per cpu partial
  mm: restrict access to slab files under procfs and sysfs
  slub: Code optimization in get_partial_node()
  slub: doc: update the slabinfo.c file path
  slub: explicitly document position of inserting slab to partial list
  slub: update slabinfo tools to report per cpu partial list statistics
  slub: per cpu cache for partial pages
  slub: return object pointer from get_partial() / new_slab().
  slub: pass kmem_cache_cpu pointer to get_partial()
  slub: Prepare inuse field in new_slab()
  slub: Remove useless statements in __slab_alloc
  slub: free slabs without holding locks
  slub: use print_hex_dump
  slab: use print_hex_dump
parents 3b3dd79d e182a345
...@@ -30,8 +30,6 @@ page_migration ...@@ -30,8 +30,6 @@ page_migration
- description of page migration in NUMA systems. - description of page migration in NUMA systems.
pagemap.txt pagemap.txt
- pagemap, from the userspace perspective - pagemap, from the userspace perspective
slabinfo.c
- source code for a tool to get reports about slabs.
slub.txt slub.txt
- a short users guide for SLUB. - a short users guide for SLUB.
unevictable-lru.txt unevictable-lru.txt
......
...@@ -79,9 +79,21 @@ struct page { ...@@ -79,9 +79,21 @@ struct page {
}; };
/* Third double word block */ /* Third double word block */
union {
struct list_head lru; /* Pageout list, eg. active_list struct list_head lru; /* Pageout list, eg. active_list
* protected by zone->lru_lock ! * protected by zone->lru_lock !
*/ */
struct { /* slub per cpu partial pages */
struct page *next; /* Next partial slab */
#ifdef CONFIG_64BIT
int pages; /* Nr of partial slabs left */
int pobjects; /* Approximate # of objects */
#else
short int pages;
short int pobjects;
#endif
};
};
/* Remainder is not double word aligned */ /* Remainder is not double word aligned */
union { union {
......
...@@ -36,12 +36,15 @@ enum stat_item { ...@@ -36,12 +36,15 @@ enum stat_item {
ORDER_FALLBACK, /* Number of times fallback was necessary */ ORDER_FALLBACK, /* Number of times fallback was necessary */
CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */ CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */
CMPXCHG_DOUBLE_FAIL, /* Number of times that cmpxchg double did not match */ CMPXCHG_DOUBLE_FAIL, /* Number of times that cmpxchg double did not match */
CPU_PARTIAL_ALLOC, /* Used cpu partial on alloc */
CPU_PARTIAL_FREE, /* USed cpu partial on free */
NR_SLUB_STAT_ITEMS }; NR_SLUB_STAT_ITEMS };
struct kmem_cache_cpu { struct kmem_cache_cpu {
void **freelist; /* Pointer to next available object */ void **freelist; /* Pointer to next available object */
unsigned long tid; /* Globally unique transaction id */ unsigned long tid; /* Globally unique transaction id */
struct page *page; /* The slab from which we are allocating */ struct page *page; /* The slab from which we are allocating */
struct page *partial; /* Partially allocated frozen slabs */
int node; /* The node of the page (or -1 for debug) */ int node; /* The node of the page (or -1 for debug) */
#ifdef CONFIG_SLUB_STATS #ifdef CONFIG_SLUB_STATS
unsigned stat[NR_SLUB_STAT_ITEMS]; unsigned stat[NR_SLUB_STAT_ITEMS];
...@@ -79,6 +82,7 @@ struct kmem_cache { ...@@ -79,6 +82,7 @@ struct kmem_cache {
int size; /* The size of an object including meta data */ int size; /* The size of an object including meta data */
int objsize; /* The size of an object without meta data */ int objsize; /* The size of an object without meta data */
int offset; /* Free pointer offset. */ int offset; /* Free pointer offset. */
int cpu_partial; /* Number of per cpu partial objects to keep around */
struct kmem_cache_order_objects oo; struct kmem_cache_order_objects oo;
/* Allocation and freeing of slabs */ /* Allocation and freeing of slabs */
......
...@@ -1851,15 +1851,15 @@ static void dump_line(char *data, int offset, int limit) ...@@ -1851,15 +1851,15 @@ static void dump_line(char *data, int offset, int limit)
unsigned char error = 0; unsigned char error = 0;
int bad_count = 0; int bad_count = 0;
printk(KERN_ERR "%03x:", offset); printk(KERN_ERR "%03x: ", offset);
for (i = 0; i < limit; i++) { for (i = 0; i < limit; i++) {
if (data[offset + i] != POISON_FREE) { if (data[offset + i] != POISON_FREE) {
error = data[offset + i]; error = data[offset + i];
bad_count++; bad_count++;
} }
printk(" %02x", (unsigned char)data[offset + i]);
} }
printk("\n"); print_hex_dump(KERN_CONT, "", 0, 16, 1,
&data[offset], limit, 1);
if (bad_count == 1) { if (bad_count == 1) {
error ^= POISON_FREE; error ^= POISON_FREE;
...@@ -3039,14 +3039,9 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) ...@@ -3039,14 +3039,9 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp)
printk(KERN_ERR "slab: Internal list corruption detected in " printk(KERN_ERR "slab: Internal list corruption detected in "
"cache '%s'(%d), slabp %p(%d). Hexdump:\n", "cache '%s'(%d), slabp %p(%d). Hexdump:\n",
cachep->name, cachep->num, slabp, slabp->inuse); cachep->name, cachep->num, slabp, slabp->inuse);
for (i = 0; print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, slabp,
i < sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t); sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t),
i++) { 1);
if (i % 16 == 0)
printk("\n%03x:", i);
printk(" %02x", ((unsigned char *)slabp)[i]);
}
printk("\n");
BUG(); BUG();
} }
} }
...@@ -4584,7 +4579,7 @@ static const struct file_operations proc_slabstats_operations = { ...@@ -4584,7 +4579,7 @@ static const struct file_operations proc_slabstats_operations = {
static int __init slab_proc_init(void) static int __init slab_proc_init(void)
{ {
proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations); proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
#ifdef CONFIG_DEBUG_SLAB_LEAK #ifdef CONFIG_DEBUG_SLAB_LEAK
proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
#endif #endif
......
This diff is collapsed.
...@@ -42,6 +42,7 @@ struct slabinfo { ...@@ -42,6 +42,7 @@ struct slabinfo {
unsigned long deactivate_remote_frees, order_fallback; unsigned long deactivate_remote_frees, order_fallback;
unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail; unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
unsigned long alloc_node_mismatch, deactivate_bypass; unsigned long alloc_node_mismatch, deactivate_bypass;
unsigned long cpu_partial_alloc, cpu_partial_free;
int numa[MAX_NODES]; int numa[MAX_NODES];
int numa_partial[MAX_NODES]; int numa_partial[MAX_NODES];
} slabinfo[MAX_SLABS]; } slabinfo[MAX_SLABS];
...@@ -455,6 +456,11 @@ static void slab_stats(struct slabinfo *s) ...@@ -455,6 +456,11 @@ static void slab_stats(struct slabinfo *s)
s->alloc_from_partial * 100 / total_alloc, s->alloc_from_partial * 100 / total_alloc,
s->free_remove_partial * 100 / total_free); s->free_remove_partial * 100 / total_free);
printf("Cpu partial list %8lu %8lu %3lu %3lu\n",
s->cpu_partial_alloc, s->cpu_partial_free,
s->cpu_partial_alloc * 100 / total_alloc,
s->cpu_partial_free * 100 / total_free);
printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n", printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
s->deactivate_remote_frees, s->free_frozen, s->deactivate_remote_frees, s->free_frozen,
s->deactivate_remote_frees * 100 / total_alloc, s->deactivate_remote_frees * 100 / total_alloc,
...@@ -1145,7 +1151,7 @@ static void read_slab_dir(void) ...@@ -1145,7 +1151,7 @@ static void read_slab_dir(void)
switch (de->d_type) { switch (de->d_type) {
case DT_LNK: case DT_LNK:
alias->name = strdup(de->d_name); alias->name = strdup(de->d_name);
count = readlink(de->d_name, buffer, sizeof(buffer)); count = readlink(de->d_name, buffer, sizeof(buffer)-1);
if (count < 0) if (count < 0)
fatal("Cannot read symlink %s\n", de->d_name); fatal("Cannot read symlink %s\n", de->d_name);
...@@ -1209,6 +1215,8 @@ static void read_slab_dir(void) ...@@ -1209,6 +1215,8 @@ static void read_slab_dir(void)
slab->order_fallback = get_obj("order_fallback"); slab->order_fallback = get_obj("order_fallback");
slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail"); slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail"); slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
slab->cpu_partial_alloc = get_obj("cpu_partial_alloc");
slab->cpu_partial_free = get_obj("cpu_partial_free");
slab->alloc_node_mismatch = get_obj("alloc_node_mismatch"); slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
slab->deactivate_bypass = get_obj("deactivate_bypass"); slab->deactivate_bypass = get_obj("deactivate_bypass");
chdir(".."); chdir("..");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment