* the fast path and disables lockless freelists.
*/
+++ +#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
+++ + SLAB_TRACE | SLAB_DEBUG_FREE)
+++ +
+++ +static inline int kmem_cache_debug(struct kmem_cache *s)
+++ +{
#ifdef CONFIG_SLUB_DEBUG
--- -#define SLABDEBUG 1
+++ + return unlikely(s->flags & SLAB_DEBUG_FLAGS);
#else
--- -#define SLABDEBUG 0
+++ + return 0;
#endif
+++ +}
/*
* Issues still to be resolved:
#define MAX_OBJS_PER_PAGE 65535 /* since page.objects is u16 */
/* Internal SLUB flags */
--- -#define __OBJECT_POISON 0x80000000 /* Poison object */
--- -#define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */
+++ +#define __OBJECT_POISON 0x80000000UL /* Poison object */
+++ +#define __SYSFS_ADD_DEFERRED 0x40000000UL /* Not yet visible via sysfs */
static int kmem_size = sizeof(struct kmem_cache);
flags |= __GFP_NOTRACK;
--- - if (node == -1)
+++ + if (node == NUMA_NO_NODE)
return alloc_pages(flags, order);
else
return alloc_pages_exact_node(node, flags, order);
inc_slabs_node(s, page_to_nid(page), page->objects);
page->slab = s;
page->flags |= 1 << PG_slab;
--- - if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
--- - SLAB_STORE_USER | SLAB_TRACE))
--- - __SetPageSlubDebug(page);
start = page_address(page);
int order = compound_order(page);
int pages = 1 << order;
--- - if (unlikely(SLABDEBUG && PageSlubDebug(page))) {
+++ + if (kmem_cache_debug(s)) {
void *p;
slab_pad_check(s, page);
for_each_object(p, s, page_address(page),
page->objects)
check_object(s, page, p, 0);
--- - __ClearPageSlubDebug(page);
}
kmemcheck_free_shadow(page, compound_order(page));
static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node)
{
struct page *page;
--- - int searchnode = (node == -1) ? numa_node_id() : node;
+++ + int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node;
page = get_partial_node(get_node(s, searchnode));
---- if (page || (flags & __GFP_THISNODE))
++++ if (page || node != -1)
return page;
return get_any_partial(s, flags);
stat(s, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
} else {
stat(s, DEACTIVATE_FULL);
--- - if (SLABDEBUG && PageSlubDebug(page) &&
--- - (s->flags & SLAB_STORE_USER))
+++ + if (kmem_cache_debug(s) && (s->flags & SLAB_STORE_USER))
add_full(n, page);
}
slab_unlock(page);
static inline int node_match(struct kmem_cache_cpu *c, int node)
{
#ifdef CONFIG_NUMA
--- - if (node != -1 && c->node != node)
+++ + if (node != NUMA_NO_NODE && c->node != node)
return 0;
#endif
return 1;
object = c->page->freelist;
if (unlikely(!object))
goto another_slab;
--- - if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
+++ + if (kmem_cache_debug(s))
goto debug;
c->freelist = get_freepointer(s, object);
void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
{
--- - void *ret = slab_alloc(s, gfpflags, -1, _RET_IP_);
+++ + void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_);
trace_kmem_cache_alloc(_RET_IP_, ret, s->objsize, s->size, gfpflags);
#ifdef CONFIG_TRACING
void *kmem_cache_alloc_notrace(struct kmem_cache *s, gfp_t gfpflags)
{
--- - return slab_alloc(s, gfpflags, -1, _RET_IP_);
+++ + return slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_);
}
EXPORT_SYMBOL(kmem_cache_alloc_notrace);
#endif
stat(s, FREE_SLOWPATH);
slab_lock(page);
--- - if (unlikely(SLABDEBUG && PageSlubDebug(page)))
+++ + if (kmem_cache_debug(s))
goto debug;
checks_ok:
s->refcount--;
if (!s->refcount) {
list_del(&s->list);
--- - up_write(&slub_lock);
if (kmem_cache_close(s)) {
printk(KERN_ERR "SLUB %s: %s called for cache that "
"still has objects.\n", s->name, __func__);
if (s->flags & SLAB_DESTROY_BY_RCU)
rcu_barrier();
sysfs_slab_remove(s);
--- - } else
--- - up_write(&slub_lock);
+++ + }
+++ + up_write(&slub_lock);
}
EXPORT_SYMBOL(kmem_cache_destroy);
if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
--- - ret = slab_alloc(s, flags, -1, _RET_IP_);
+++ + ret = slab_alloc(s, flags, NUMA_NO_NODE, _RET_IP_);
trace_kmalloc(_RET_IP_, ret, size, s->size, flags);
slab_state = UP;
/* Provide the correct kmalloc names now that the caches are up */
--- - for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++)
--- - kmalloc_caches[i]. name =
--- - kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
+++ + for (i = KMALLOC_SHIFT_LOW; i < SLUB_PAGE_SHIFT; i++) {
+++ + char *s = kasprintf(GFP_NOWAIT, "kmalloc-%d", 1 << i);
+++ +
+++ + BUG_ON(!s);
+++ + kmalloc_caches[i].name = s;
+++ + }
#ifdef CONFIG_SMP
register_cpu_notifier(&slab_notifier);
*/
s->objsize = max(s->objsize, (int)size);
s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
--- - up_write(&slub_lock);
if (sysfs_slab_alias(s, name)) {
--- - down_write(&slub_lock);
s->refcount--;
--- - up_write(&slub_lock);
goto err;
}
+++ + up_write(&slub_lock);
return s;
}
if (kmem_cache_open(s, GFP_KERNEL, name,
size, align, flags, ctor)) {
list_add(&s->list, &slab_caches);
--- - up_write(&slub_lock);
if (sysfs_slab_add(s)) {
--- - down_write(&slub_lock);
list_del(&s->list);
--- - up_write(&slub_lock);
kfree(s);
goto err;
}
+++ + up_write(&slub_lock);
return s;
}
kfree(s);
if (unlikely(ZERO_OR_NULL_PTR(s)))
return s;
--- - ret = slab_alloc(s, gfpflags, -1, caller);
+++ + ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, caller);
/* Honor the call site pointer we recieved. */
trace_kmalloc(caller, ret, size, s->size, gfpflags);
} else
printk(KERN_INFO "SLUB %s: Skipped busy slab 0x%p\n",
s->name, page);
--- -
--- - if (s->flags & DEBUG_DEFAULT_FLAGS) {
--- - if (!PageSlubDebug(page))
--- - printk(KERN_ERR "SLUB %s: SlubDebug not set "
--- - "on slab 0x%p\n", s->name, page);
--- - } else {
--- - if (PageSlubDebug(page))
--- - printk(KERN_ERR "SLUB %s: SlubDebug set on "
--- - "slab 0x%p\n", s->name, page);
--- - }
}
static int validate_slab_node(struct kmem_cache *s,
static void sysfs_slab_remove(struct kmem_cache *s)
{
+++ + if (slab_state < SYSFS)
+++ + /*
+++ + * Sysfs has not been setup yet so no need to remove the
+++ + * cache from sysfs.
+++ + */
+++ + return;
+++ +
kobject_uevent(&s->kobj, KOBJ_REMOVE);
kobject_del(&s->kobj);
kobject_put(&s->kobj);
struct kmem_cache *s;
int err;
+++ + down_write(&slub_lock);
+++ +
slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj);
if (!slab_kset) {
+++ + up_write(&slub_lock);
printk(KERN_ERR "Cannot register slab subsystem.\n");
return -ENOSYS;
}
kfree(al);
}
+++ + up_write(&slub_lock);
resiliency_test();
return 0;
}