]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ceph: bookkeeper handles kmem_cache allocations
authorYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 3 Dec 2009 22:49:17 +0000 (14:49 -0800)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 14 Dec 2009 19:41:55 +0000 (11:41 -0800)
fs/ceph/bookkeeper.c
fs/ceph/bookkeeper.h

index 5d244edf3118aa8350a5a091698fff055e739e31..c7238360c3db33bc4d19d2f50496bb009ce8051a 100644 (file)
@@ -19,69 +19,169 @@ static DEFINE_SPINLOCK(_bk_lock);
 
 static size_t _total_alloc;
 static size_t _total_free;
+static size_t _total_kc_alloc;
+static size_t _total_kc_free;
+
+#define ALLOC_TYPE_KALLOC      0x1
+#define ALLOC_TYPE_KMEMCACHE   0x2
 
 struct alloc_data {
        u32 prefix_magic;
        size_t size;
+       int alloc_type;
        struct list_head node;
-       char *fname;
+       const char *fname;
        int line;
        u32 suffix_magic;
 };
 
-void *ceph_kmalloc(char *fname, int line, size_t size, gfp_t flags)
-{
-       struct alloc_data *p = kmalloc(size+sizeof(struct alloc_data), flags);
+struct ceph_kmemcache {
+       struct kmem_cache *cache;
+       size_t alloc_size;
+       void (*ctor)(void *);
+};
 
-       if (!p)
-               return NULL;
+static void bk_init_header(struct alloc_data *header, size_t size, int alloc_type)
+{
+       header->prefix_magic = CEPH_BK_MAGIC;
+       header->size = size;
+       header->alloc_type = alloc_type;
+       header->suffix_magic = CEPH_BK_MAGIC;
+}
 
-       p->prefix_magic = CEPH_BK_MAGIC;
-       p->size = size;
-       p->fname = fname;
-       p->line = line;
-       p->suffix_magic = CEPH_BK_MAGIC;
+static void bk_insert_alloc(struct alloc_data *header, const char *fname, int line, size_t size)
+{
+       header->line = line;
+       header->fname = fname;
 
        spin_lock(&_bk_lock);
        _total_alloc += size;
+       if (header->alloc_type == ALLOC_TYPE_KMEMCACHE) {
+               _total_kc_alloc += size;
+       }
 
-       list_add_tail(&p->node, &_bk_allocs);
+       list_add_tail(&header->node, &_bk_allocs);
        spin_unlock(&_bk_lock);
-
-       return ((void *)p)+sizeof(struct alloc_data);
 }
 
-void ceph_kfree(const void *ptr)
+static void bk_remove_alloc(struct alloc_data *header)
 {
-       struct alloc_data *p = (struct alloc_data *)(ptr -
-                                                    sizeof(struct alloc_data));
        int overrun = 0;
 
-       if (!ptr)
-               return;
-
-       if (p->prefix_magic != CEPH_BK_MAGIC) {
+       if (header->prefix_magic != CEPH_BK_MAGIC) {
                printk(KERN_ERR "ERROR: memory overrun (under)!\n");
                overrun = 1;
        }
 
-       if (p->suffix_magic != CEPH_BK_MAGIC) {
+       if (header->suffix_magic != CEPH_BK_MAGIC) {
                printk(KERN_ERR "ERROR: Memory overrun (over)!\n");
                overrun = 1;
        }
 
        if (overrun) {
                printk(KERN_ERR "Memory allocated at %s(%d): p=%p (%zu bytes)\n",
-                    p->fname, p->line, ((void *)p)+sizeof(struct alloc_data),
-                    p->size);
+                    header->fname, header->line, ((void *)header)+sizeof(struct alloc_data),
+                    header->size);
        }
 
        BUG_ON(overrun);
 
        spin_lock(&_bk_lock);
-       _total_free += p->size;
-       list_del(&p->node);
+       _total_free += header->size;
+       if (header->alloc_type == ALLOC_TYPE_KMEMCACHE) {
+               _total_kc_free += header->size;
+       }
+       list_del(&header->node);
        spin_unlock(&_bk_lock);
+}
+
+struct kmem_cache *
+ceph_kmem_cache_create(const char *name, size_t size, size_t align,
+                            unsigned long flags, void (*ctor)(void *))
+{
+       struct ceph_kmemcache *ceph_cache;
+
+       ceph_cache = (struct ceph_kmemcache *)kmalloc(
+                                               sizeof(struct ceph_kmemcache),
+                                               GFP_KERNEL);
+       if (!ceph_cache)
+               return NULL;
+
+
+       ceph_cache->cache = kmem_cache_create(name, size + sizeof(struct alloc_data),
+                               __alignof__(align + sizeof(struct alloc_data)),
+                               flags, NULL);
+       ceph_cache->alloc_size = size; 
+       ceph_cache->ctor = ctor;
+
+       return (struct kmem_cache *)ceph_cache;
+}
+
+void ceph_kmem_cache_destroy(struct kmem_cache *cachep)
+{
+       struct ceph_kmemcache *ceph_cache = (struct ceph_kmemcache *)cachep;
+
+       kmem_cache_destroy(ceph_cache->cache);
+
+       kfree(ceph_cache);
+}
+
+void *ceph_kmem_cache_alloc(char *fname, int line, struct kmem_cache *cachep,
+                          gfp_t flags)
+{
+       struct ceph_kmemcache *ceph_cache = (struct ceph_kmemcache *)cachep;
+       struct alloc_data *header =
+               (struct alloc_data *)kmem_cache_alloc(ceph_cache->cache, flags);
+       void *p;
+
+       if (!header)
+               return NULL;
+
+       p = (void *)(header + 1);
+
+       if (header->prefix_magic != CEPH_BK_MAGIC) {
+               bk_init_header(header, ceph_cache->alloc_size, ALLOC_TYPE_KMEMCACHE);
+
+               if (ceph_cache->ctor)
+                       ceph_cache->ctor(p);
+       }
+       bk_insert_alloc(header, fname, line, ceph_cache->alloc_size);
+
+       return p;
+}
+
+void ceph_kmem_cache_free(struct kmem_cache *cachep, void *objp)
+{
+       struct ceph_kmemcache *ceph_cache = (struct ceph_kmemcache *)cachep;
+       struct alloc_data *p = (struct alloc_data *)(objp -
+                                                    sizeof(struct alloc_data));
+       
+       bk_remove_alloc(p);
+       kmem_cache_free(ceph_cache->cache, p);
+}
+
+
+void *ceph_kmalloc(char *fname, int line, size_t size, gfp_t flags)
+{
+       struct alloc_data *p = kmalloc(size+sizeof(struct alloc_data), flags);
+
+       if (!p)
+               return NULL;
+
+       bk_init_header(p, size, ALLOC_TYPE_KALLOC);
+       bk_insert_alloc(p, fname, line, size);
+
+       return (void *)(p + 1);
+}
+
+void ceph_kfree(const void *ptr)
+{
+       struct alloc_data *p = (struct alloc_data *)(ptr -
+                                                    sizeof(struct alloc_data));
+       if (!ptr)
+               return;
+
+       bk_remove_alloc(p);
 
        kfree(p);
 
@@ -96,6 +196,8 @@ void ceph_bookkeeper_dump(void)
 
        printk(KERN_ERR "bookkeeper: total bytes alloc: %zu\n", _total_alloc);
        printk(KERN_ERR "bookkeeper: total bytes free: %zu\n", _total_free);
+       printk(KERN_ERR "bookkeeper: (kmem_cache) total bytes alloc: %zu\n", _total_kc_alloc);
+       printk(KERN_ERR "bookkeeper: (kmem_cache) total bytes free: %zu\n", _total_kc_free);
 
        if (_total_alloc != _total_free) {
                list_for_each(p, &_bk_allocs) {
@@ -106,7 +208,7 @@ void ceph_bookkeeper_dump(void)
                             entry->size);
                }
        } else {
-               dout("No leaks found! Yay!\n");
+               printk(KERN_ERR "No leaks found! Yay!\n");
        }
 }
 
@@ -156,6 +258,11 @@ void ceph_bookkeeper_init(void)
        printk(KERN_ERR "bookkeeper: start\n");
        dout("bookkeeper: start\n");
        INIT_LIST_HEAD(&_bk_allocs);
+
+       _total_alloc = 0;
+       _total_free = 0;
+       _total_kc_alloc = 0;
+       _total_kc_free = 0;
 }
 
 void ceph_bookkeeper_finalize(void)
index b9b437c125c3b36869638f98f3a98f72f2dc15f3..db7f9738d97a5e13a96d914fa242ed122f68d355 100644 (file)
@@ -15,6 +15,16 @@ extern char *ceph_kstrndup(char *fname, int line, const char *src, int n, gfp_t
 
 extern void ceph_kfree(const void *ptr);
 
+extern struct kmem_cache *ceph_kmem_cache_create(const char *name,
+                       size_t size, size_t align,
+                       unsigned long flags, void (*ctor)(void *));
+extern void ceph_kmem_cache_destroy(struct kmem_cache *cachep);
+
+extern void *ceph_kmem_cache_alloc(char *fname, int line, struct kmem_cache *cachep,
+                          gfp_t flags);
+
+extern void ceph_kmem_cache_free(struct kmem_cache *cachep, void *objp);
+
 #endif
 
 
@@ -30,6 +40,13 @@ extern void ceph_kfree(const void *ptr);
 #define kstrndup(src, n, flags)        ceph_kstrndup(__FILE__, __LINE__, \
                                                      src, n, flags)
 #define kfree  ceph_kfree
+
+#define kmem_cache_create      ceph_kmem_cache_create
+#define kmem_cache_destroy     ceph_kmem_cache_destroy
+#define kmem_cache_alloc(cachep, flags) \
+                       ceph_kmem_cache_alloc(__FILE__, __LINE__, cachep, flags)
+#define kmem_cache_free                ceph_kmem_cache_free
+
 #endif
 
 #ifdef CEPH_DISABLE_BOOKKEEPER
@@ -40,6 +57,10 @@ extern void ceph_kfree(const void *ptr);
 #undef kstrdup
 #undef kstrndup
 #undef kfree
+#undef kmem_cache_create
+#undef kmem_cache_destroy
+#undef kmem_cache_alloc
+#undef kmem_cache_free
 #endif
 #endif