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.
#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
*/
ret = journal_init_revoke_caches();
if (ret == 0)
ret = journal_init_journal_head_cache();
+ if (ret == 0)
+ ret = journal_init_handle_cache();
return ret;
}
{
journal_destroy_revoke_caches();
journal_destroy_journal_head_cache();
+ journal_destroy_handle_cache();
}
static int __init journal_init(void)
/* 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);
err = start_this_handle(journal, handle);
if (err < 0) {
- kfree(handle);
+ jbd_free_handle(handle);
current->journal_info = NULL;
return ERR_PTR(err);
}
if (handle->h_sync && !(current->flags & PF_MEMALLOC))
log_wait_commit(journal, tid);
}
- kfree(handle);
+ jbd_free_handle(handle);
return err;
}
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);