Index: linux-2.6/mm/slob.c =================================================================== --- linux-2.6.orig/mm/slob.c 2007-04-12 14:35:11.000000000 +1000 +++ linux-2.6/mm/slob.c 2007-05-09 11:01:09.000000000 +1000 @@ -35,6 +35,7 @@ #include #include #include +#include struct slob_block { int units; @@ -53,6 +54,11 @@ }; typedef struct bigblock bigblock_t; +struct slob_rcu { + struct rcu_head rcu_head; + struct kmem_cache *c; +}; + static slob_t arena = { .next = &arena, .units = 1 }; static slob_t *slobfree = &arena; static bigblock_t *bigblocks; @@ -242,6 +248,7 @@ struct kmem_cache { unsigned int size, align; + unsigned long flags; const char *name; void (*ctor)(void *, struct kmem_cache *, unsigned long); void (*dtor)(void *, struct kmem_cache *, unsigned long); @@ -259,6 +266,11 @@ if (c) { c->name = name; c->size = size; + if (flags & SLAB_DESTROY_BY_RCU) { + /* leave room for rcu footer at the end of object */ + c->size += sizeof(struct slob_rcu); + } + c->flags = flags; c->ctor = ctor; c->dtor = dtor; /* ignore alignment unless it's forced */ @@ -281,9 +293,9 @@ { void *b; - if (c->size < PAGE_SIZE) + if (c->size < PAGE_SIZE) { b = slob_alloc(c->size, flags, c->align); - else + } else b = (void *)__get_free_pages(flags, find_order(c->size)); if (c->ctor) @@ -303,7 +315,7 @@ } EXPORT_SYMBOL(kmem_cache_zalloc); -void kmem_cache_free(struct kmem_cache *c, void *b) +static void __kmem_cache_free(struct kmem_cache *c, void *b) { if (c->dtor) c->dtor(b, c, 0); @@ -313,6 +325,25 @@ else free_pages((unsigned long)b, find_order(c->size)); } + +static void kmem_rcu_free(struct rcu_head *head) +{ + struct slob_rcu *slob_rcu = (struct slob_rcu *)head; + void *b = (void *)slob_rcu - slob_rcu->c->size; + + __kmem_cache_free(b, slob_rcu->c); +} + +void kmem_cache_free(struct kmem_cache *c, void *b) +{ + if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) { + struct slob_rcu *slob_rcu; + slob_rcu = b + c->size;; + slob_rcu->c = c; + call_rcu(&slob_rcu->rcu_head, kmem_rcu_free); + } else + __kmem_cache_free(b, c); +} EXPORT_SYMBOL(kmem_cache_free); unsigned int kmem_cache_size(struct kmem_cache *c) Index: linux-2.6/init/Kconfig =================================================================== --- linux-2.6.orig/init/Kconfig 2007-04-12 14:35:11.000000000 +1000 +++ linux-2.6/init/Kconfig 2007-05-09 09:11:14.000000000 +1000 @@ -476,7 +476,7 @@ config SLAB default y - bool "Use full SLAB allocator" if (EMBEDDED && !SMP && !SPARSEMEM) + bool "Use full SLAB allocator" if (EMBEDDED && !SPARSEMEM) help Disabling this replaces the advanced SLAB allocator and kmalloc support with the drastically simpler SLOB allocator.