static struct ext4_lazy_init *ext4_li_info;
 static struct mutex ext4_li_mtx;
 static struct ext4_features *ext4_feat;
+static int ext4_mballoc_ready;
 
 static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
                             unsigned long journal_devnum);
                invalidate_bdev(sbi->journal_bdev);
                ext4_blkdev_remove(sbi);
        }
+       if (sbi->s_mb_cache) {
+               ext4_xattr_destroy_cache(sbi->s_mb_cache);
+               sbi->s_mb_cache = NULL;
+       }
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
        sb->s_fs_info = NULL;
        percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);
 
 no_journal:
+       if (ext4_mballoc_ready) {
+               sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id);
+               if (!sbi->s_mb_cache) {
+                       ext4_msg(sb, KERN_ERR, "Failed to create an mb_cache");
+                       goto failed_mount_wq;
+               }
+       }
+
        /*
         * Get the # of file system overhead blocks from the
         * superblock if present.
                goto out4;
 
        err = ext4_init_mballoc();
-       if (err)
-               goto out3;
-
-       err = ext4_init_xattr();
        if (err)
                goto out2;
+       else
+               ext4_mballoc_ready = 1;
        err = init_inodecache();
        if (err)
                goto out1;
        unregister_as_ext3();
        destroy_inodecache();
 out1:
-       ext4_exit_xattr();
-out2:
+       ext4_mballoc_ready = 0;
        ext4_exit_mballoc();
-out3:
+out2:
        ext4_exit_feat_adverts();
 out4:
        if (ext4_proc_root)
        unregister_as_ext3();
        unregister_filesystem(&ext4_fs_type);
        destroy_inodecache();
-       ext4_exit_xattr();
        ext4_exit_mballoc();
        ext4_exit_feat_adverts();
        remove_proc_entry("fs/ext4", NULL);
 
 # define ea_bdebug(bh, fmt, ...)       no_printk(fmt, ##__VA_ARGS__)
 #endif
 
-static void ext4_xattr_cache_insert(struct buffer_head *);
+static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *);
 static struct buffer_head *ext4_xattr_cache_find(struct inode *,
                                                 struct ext4_xattr_header *,
                                                 struct mb_cache_entry **);
 static int ext4_xattr_list(struct dentry *dentry, char *buffer,
                           size_t buffer_size);
 
-static struct mb_cache *ext4_xattr_cache;
-
 static const struct xattr_handler *ext4_xattr_handler_map[] = {
        [EXT4_XATTR_INDEX_USER]              = &ext4_xattr_user_handler,
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
        NULL
 };
 
+#define EXT4_GET_MB_CACHE(inode)       (((struct ext4_sb_info *) \
+                               inode->i_sb->s_fs_info)->s_mb_cache)
+
 static __le32 ext4_xattr_block_csum(struct inode *inode,
                                    sector_t block_nr,
                                    struct ext4_xattr_header *hdr)
        struct ext4_xattr_entry *entry;
        size_t size;
        int error;
+       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
        ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
                  name_index, name, buffer, (long)buffer_size);
                error = -EIO;
                goto cleanup;
        }
-       ext4_xattr_cache_insert(bh);
+       ext4_xattr_cache_insert(ext4_mb_cache, bh);
        entry = BFIRST(bh);
        error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
        if (error == -EIO)
        struct inode *inode = dentry->d_inode;
        struct buffer_head *bh = NULL;
        int error;
+       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
        ea_idebug(inode, "buffer=%p, buffer_size=%ld",
                  buffer, (long)buffer_size);
                error = -EIO;
                goto cleanup;
        }
-       ext4_xattr_cache_insert(bh);
+       ext4_xattr_cache_insert(ext4_mb_cache, bh);
        error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
 
 cleanup:
 {
        struct mb_cache_entry *ce = NULL;
        int error = 0;
+       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
-       ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
+       ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr);
        error = ext4_journal_get_write_access(handle, bh);
        if (error)
                goto out;
        struct ext4_xattr_search *s = &bs->s;
        struct mb_cache_entry *ce = NULL;
        int error = 0;
+       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
 #define header(x) ((struct ext4_xattr_header *)(x))
 
        if (i->value && i->value_len > sb->s_blocksize)
                return -ENOSPC;
        if (s->base) {
-               ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
+               ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev,
                                        bs->bh->b_blocknr);
                error = ext4_journal_get_write_access(handle, bs->bh);
                if (error)
                                if (!IS_LAST_ENTRY(s->first))
                                        ext4_xattr_rehash(header(s->base),
                                                          s->here);
-                               ext4_xattr_cache_insert(bs->bh);
+                               ext4_xattr_cache_insert(ext4_mb_cache,
+                                       bs->bh);
                        }
                        unlock_buffer(bs->bh);
                        if (error == -EIO)
                        memcpy(new_bh->b_data, s->base, new_bh->b_size);
                        set_buffer_uptodate(new_bh);
                        unlock_buffer(new_bh);
-                       ext4_xattr_cache_insert(new_bh);
+                       ext4_xattr_cache_insert(ext4_mb_cache, new_bh);
                        error = ext4_handle_dirty_xattr_block(handle,
                                                              inode, new_bh);
                        if (error)
  * Returns 0, or a negative error number on failure.
  */
 static void
-ext4_xattr_cache_insert(struct buffer_head *bh)
+ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh)
 {
        __u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
        struct mb_cache_entry *ce;
        int error;
 
-       ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS);
+       ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS);
        if (!ce) {
                ea_bdebug(bh, "out of memory");
                return;
 {
        __u32 hash = le32_to_cpu(header->h_hash);
        struct mb_cache_entry *ce;
+       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
 
        if (!header->h_hash)
                return NULL;  /* never share */
        ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
 again:
-       ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev,
+       ce = mb_cache_entry_find_first(ext4_mb_cache, inode->i_sb->s_bdev,
                                       hash);
        while (ce) {
                struct buffer_head *bh;
 
 #undef BLOCK_HASH_SHIFT
 
-int __init
-ext4_init_xattr(void)
+#define        HASH_BUCKET_BITS        10
+
+struct mb_cache *
+ext4_xattr_create_cache(char *name)
 {
-       ext4_xattr_cache = mb_cache_create("ext4_xattr", 6);
-       if (!ext4_xattr_cache)
-               return -ENOMEM;
-       return 0;
+       return mb_cache_create(name, HASH_BUCKET_BITS);
 }
 
-void
-ext4_exit_xattr(void)
+void ext4_xattr_destroy_cache(struct mb_cache *cache)
 {
-       if (ext4_xattr_cache)
-               mb_cache_destroy(ext4_xattr_cache);
-       ext4_xattr_cache = NULL;
+       if (cache)
+               mb_cache_destroy(cache);
 }
+
 
 
 static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
 static struct blockgroup_lock *mb_cache_bg_lock;
+static struct kmem_cache *mb_cache_kmem_cache;
 
 MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
 MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
                goto fail;
        for (n=0; n<bucket_count; n++)
                INIT_HLIST_BL_HEAD(&cache->c_index_hash[n]);
-       cache->c_entry_cache = kmem_cache_create(name,
-               sizeof(struct mb_cache_entry), 0,
-               SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
-       if (!cache->c_entry_cache)
-               goto fail2;
+       if (!mb_cache_kmem_cache) {
+               mb_cache_kmem_cache = kmem_cache_create(name,
+                       sizeof(struct mb_cache_entry), 0,
+                       SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+               if (!mb_cache_kmem_cache)
+                       goto fail2;
+       }
+       cache->c_entry_cache = mb_cache_kmem_cache;
 
        /*
         * Set an upper limit on the number of cache entries so that the hash
                          atomic_read(&cache->c_entry_count));
        }
 
+       if (list_empty(&mb_cache_list)) {
+               kmem_cache_destroy(mb_cache_kmem_cache);
+               mb_cache_kmem_cache = NULL;
+       }
        kfree(cache->c_index_hash);
        kfree(cache->c_block_hash);
        kfree(cache);