The patch titled Subject: radix tree test suite: cache recently freed objects has been added to the -mm tree. Its filename is radix-tree-test-suite-cache-recently-freed-objects.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/radix-tree-test-suite-cache-recently-freed-objects.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/radix-tree-test-suite-cache-recently-freed-objects.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx> Subject: radix tree test suite: cache recently freed objects The kmem_cache_alloc implementation simply allocates new memory from malloc() and calls the ctor, which zeroes out the entire object. This means it cannot spot bugs where the object isn't properly reinitialised before being freed. Add a small (11 objects) cache before freeing objects back to malloc. This is enough to let us write a test to catch it, although the memory allocator is now aware of the structure of the radix tree node, since it chains free objects through ->private_data (like the percpu cache does). Link: http://lkml.kernel.org/r/1481667692-14500-2-git-send-email-mawilcox@xxxxxxxxxxxxxxxxx Signed-off-by: Matthew Wilcox <mawilcox@xxxxxxxxxxxxx> Cc: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> Cc: Konstantin Khlebnikov <koct9i@xxxxxxxxx> Cc: Ross Zwisler <ross.zwisler@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- tools/testing/radix-tree/linux.c | 48 ++++++++++++++++++++---- tools/testing/radix-tree/linux/slab.h | 5 -- 2 files changed, 41 insertions(+), 12 deletions(-) diff -puN tools/testing/radix-tree/linux.c~radix-tree-test-suite-cache-recently-freed-objects tools/testing/radix-tree/linux.c --- a/tools/testing/radix-tree/linux.c~radix-tree-test-suite-cache-recently-freed-objects +++ a/tools/testing/radix-tree/linux.c @@ -1,16 +1,27 @@ #include <stdlib.h> #include <string.h> #include <malloc.h> +#include <pthread.h> #include <unistd.h> #include <assert.h> #include <linux/mempool.h> +#include <linux/poison.h> #include <linux/slab.h> +#include <linux/radix-tree.h> #include <urcu/uatomic.h> int nr_allocated; int preempt_count; +struct kmem_cache { + pthread_mutex_t lock; + int size; + int nr_objs; + void *objs; + void (*ctor)(void *); +}; + void *mempool_alloc(mempool_t *pool, int gfp_mask) { return pool->alloc(gfp_mask, pool->data); @@ -34,24 +45,44 @@ mempool_t *mempool_create(int min_nr, me void *kmem_cache_alloc(struct kmem_cache *cachep, int flags) { - void *ret; + struct radix_tree_node *node; if (flags & __GFP_NOWARN) return NULL; - ret = malloc(cachep->size); - if (cachep->ctor) - cachep->ctor(ret); + pthread_mutex_lock(&cachep->lock); + if (cachep->nr_objs) { + cachep->nr_objs--; + node = cachep->objs; + cachep->objs = node->private_data; + pthread_mutex_unlock(&cachep->lock); + node->private_data = NULL; + } else { + pthread_mutex_unlock(&cachep->lock); + node = malloc(cachep->size); + if (cachep->ctor) + cachep->ctor(node); + } + uatomic_inc(&nr_allocated); - return ret; + return node; } void kmem_cache_free(struct kmem_cache *cachep, void *objp) { assert(objp); uatomic_dec(&nr_allocated); - memset(objp, 0, cachep->size); - free(objp); + pthread_mutex_lock(&cachep->lock); + if (cachep->nr_objs > 10) { + memset(objp, POISON_FREE, cachep->size); + free(objp); + } else { + struct radix_tree_node *node = objp; + cachep->nr_objs++; + node->private_data = cachep->objs; + cachep->objs = node; + } + pthread_mutex_unlock(&cachep->lock); } void *kmalloc(size_t size, gfp_t gfp) @@ -75,7 +106,10 @@ kmem_cache_create(const char *name, size { struct kmem_cache *ret = malloc(sizeof(*ret)); + pthread_mutex_init(&ret->lock, NULL); ret->size = size; + ret->nr_objs = 0; + ret->objs = NULL; ret->ctor = ctor; return ret; } diff -puN tools/testing/radix-tree/linux/slab.h~radix-tree-test-suite-cache-recently-freed-objects tools/testing/radix-tree/linux/slab.h --- a/tools/testing/radix-tree/linux/slab.h~radix-tree-test-suite-cache-recently-freed-objects +++ a/tools/testing/radix-tree/linux/slab.h @@ -10,11 +10,6 @@ void *kmalloc(size_t size, gfp_t); void kfree(void *); -struct kmem_cache { - int size; - void (*ctor)(void *); -}; - void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); void kmem_cache_free(struct kmem_cache *cachep, void *objp); _ Patches currently in -mm which might be from mawilcox@xxxxxxxxxxxxx are radix-tree-test-suite-fix-compilation.patch radix-tree-test-suite-iteration-test-misuses-rcu.patch radix-tree-test-suite-use-rcu_barrier.patch radix-tree-test-suite-handle-exceptional-entries.patch radix-tree-test-suite-record-order-in-each-item.patch btrfs-fix-race-in-btrfs_free_dummy_fs_info.patch radix-tree-improve-multiorder-iterators.patch radix-tree-delete-radix_tree_locate_item.patch radix-tree-delete-radix_tree_range_tag_if_tagged.patch radix-tree-fix-replacement-for-multiorder-entries.patch radix-tree-test-suite-check-multiorder-iteration.patch tpm-use-idr_find-not-idr_find_slowpath.patch rxrpc-abstract-away-knowledge-of-idr-internals.patch radix-tree-test-suite-cache-recently-freed-objects.patch radix-tree-ensure-counts-are-initialised.patch radix-tree-test-suite-add-new-tag-check.patch radix-tree-test-suite-delete-unused-rcupdatec.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html