From: Andrew Morton Date: Thu, 3 Apr 2003 00:29:36 +0000 (-0800) Subject: [PATCH] ext3: create a slab cache for transaction handles X-Git-Tag: v2.5.67~29^2^2~1 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=c20fb5f15e9097986aab97812bf55679dc24c4d9;p=history.git [PATCH] ext3: create a slab cache for transaction handles ext3 allocates and frees at least one handle structure for each system call. kmalloc and kfree are apparent in the profiles. Adding a slab cache for these objects takes the overhead for a write() from 1.63 microseconds down to 1.56. --- diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 2ef05640414e..167e632c4b51 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -1907,6 +1907,29 @@ static void __exit remove_jbd_proc_entry(void) #endif +kmem_cache_t *jbd_handle_cache; + +static int __init journal_init_handle_cache(void) +{ + jbd_handle_cache = kmem_cache_create("journal_handle", + sizeof(handle_t), + 0, /* offset */ + 0, /* flags */ + NULL, /* ctor */ + NULL); /* dtor */ + if (jbd_handle_cache == NULL) { + printk(KERN_EMERG "JBD: failed to create handle cache\n"); + return -ENOMEM; + } + return 0; +} + +static void journal_destroy_handle_cache(void) +{ + if (jbd_handle_cache) + kmem_cache_destroy(jbd_handle_cache); +} + /* * Module startup and shutdown */ @@ -1918,6 +1941,8 @@ static int __init journal_init_caches(void) ret = journal_init_revoke_caches(); if (ret == 0) ret = journal_init_journal_head_cache(); + if (ret == 0) + ret = journal_init_handle_cache(); return ret; } @@ -1925,6 +1950,7 @@ static void journal_destroy_caches(void) { journal_destroy_revoke_caches(); journal_destroy_journal_head_cache(); + journal_destroy_handle_cache(); } static int __init journal_init(void) diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 15694bfcb147..74b51b7fd584 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -211,10 +211,10 @@ repeat_locked: /* Allocate a new handle. This should probably be in a slab... */ static handle_t *new_handle(int nblocks) { - handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS); + handle_t *handle = jbd_alloc_handle(GFP_NOFS); if (!handle) return NULL; - memset(handle, 0, sizeof (handle_t)); + memset(handle, 0, sizeof(*handle)); handle->h_buffer_credits = nblocks; handle->h_ref = 1; INIT_LIST_HEAD(&handle->h_jcb); @@ -258,7 +258,7 @@ handle_t *journal_start(journal_t *journal, int nblocks) err = start_this_handle(journal, handle); if (err < 0) { - kfree(handle); + jbd_free_handle(handle); current->journal_info = NULL; return ERR_PTR(err); } @@ -1404,7 +1404,7 @@ int journal_stop(handle_t *handle) if (handle->h_sync && !(current->flags & PF_MEMALLOC)) log_wait_commit(journal, tid); } - kfree(handle); + jbd_free_handle(handle); return err; } diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 34bf7c8787ec..2362b90db9e7 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -814,6 +814,21 @@ extern void journal_remove_journal_head(struct buffer_head *bh); extern void __journal_remove_journal_head(struct buffer_head *bh); extern void journal_unlock_journal_head(struct journal_head *jh); +/* + * handle management + */ +extern kmem_cache_t *jbd_handle_cache; + +static inline handle_t *jbd_alloc_handle(int gfp_flags) +{ + return kmem_cache_alloc(jbd_handle_cache, gfp_flags); +} + +static inline void jbd_free_handle(handle_t *handle) +{ + kmem_cache_free(jbd_handle_cache, handle); +} + /* Primary revoke support */ #define JOURNAL_REVOKE_DEFAULT_HASH 256 extern int journal_init_revoke(journal_t *, int);