diff options
author | T Makphaibulchoke <tmac@hp.com> | 2014-03-18 19:24:49 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-03-18 19:24:49 -0400 |
commit | 9c191f701ce9f9bc604e88a5dc69cd943daa5d3b (patch) | |
tree | 2e7a0ffa25f89e6dab1719deeb6a710405517afc | |
parent | 1f3e55fe02d12213f87869768aa2b0bad3ba9a7d (diff) |
ext4: each filesystem creates and uses its own mb_cache
This patch adds new interfaces to create and destory cache,
ext4_xattr_create_cache() and ext4_xattr_destroy_cache(), and remove
the cache creation and destory calls from ex4_init_xattr() and
ext4_exitxattr() in fs/ext4/xattr.c.
fs/ext4/super.c has been changed so that when a filesystem is mounted
a cache is allocated and attched to its ext4_sb_info structure.
fs/mbcache.c has been changed so that only one slab allocator is
allocated and used by all mbcache structures.
Signed-off-by: T. Makphaibulchoke <tmac@hp.com>
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/super.c | 25 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 51 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 6 | ||||
-rw-r--r-- | fs/mbcache.c | 18 |
5 files changed, 62 insertions, 39 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 1b3cbf8cacf9..f4f889e6df83 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1329,6 +1329,7 @@ struct ext4_sb_info { | |||
1329 | struct list_head s_es_lru; | 1329 | struct list_head s_es_lru; |
1330 | unsigned long s_es_last_sorted; | 1330 | unsigned long s_es_last_sorted; |
1331 | struct percpu_counter s_extent_cache_cnt; | 1331 | struct percpu_counter s_extent_cache_cnt; |
1332 | struct mb_cache *s_mb_cache; | ||
1332 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; | 1333 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; |
1333 | 1334 | ||
1334 | /* Ratelimit ext4 messages. */ | 1335 | /* Ratelimit ext4 messages. */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 89baee42f353..5a51af7d0335 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -59,6 +59,7 @@ static struct kset *ext4_kset; | |||
59 | static struct ext4_lazy_init *ext4_li_info; | 59 | static struct ext4_lazy_init *ext4_li_info; |
60 | static struct mutex ext4_li_mtx; | 60 | static struct mutex ext4_li_mtx; |
61 | static struct ext4_features *ext4_feat; | 61 | static struct ext4_features *ext4_feat; |
62 | static int ext4_mballoc_ready; | ||
62 | 63 | ||
63 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, | 64 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, |
64 | unsigned long journal_devnum); | 65 | unsigned long journal_devnum); |
@@ -845,6 +846,10 @@ static void ext4_put_super(struct super_block *sb) | |||
845 | invalidate_bdev(sbi->journal_bdev); | 846 | invalidate_bdev(sbi->journal_bdev); |
846 | ext4_blkdev_remove(sbi); | 847 | ext4_blkdev_remove(sbi); |
847 | } | 848 | } |
849 | if (sbi->s_mb_cache) { | ||
850 | ext4_xattr_destroy_cache(sbi->s_mb_cache); | ||
851 | sbi->s_mb_cache = NULL; | ||
852 | } | ||
848 | if (sbi->s_mmp_tsk) | 853 | if (sbi->s_mmp_tsk) |
849 | kthread_stop(sbi->s_mmp_tsk); | 854 | kthread_stop(sbi->s_mmp_tsk); |
850 | sb->s_fs_info = NULL; | 855 | sb->s_fs_info = NULL; |
@@ -4010,6 +4015,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
4010 | percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); | 4015 | percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); |
4011 | 4016 | ||
4012 | no_journal: | 4017 | no_journal: |
4018 | if (ext4_mballoc_ready) { | ||
4019 | sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id); | ||
4020 | if (!sbi->s_mb_cache) { | ||
4021 | ext4_msg(sb, KERN_ERR, "Failed to create an mb_cache"); | ||
4022 | goto failed_mount_wq; | ||
4023 | } | ||
4024 | } | ||
4025 | |||
4013 | /* | 4026 | /* |
4014 | * Get the # of file system overhead blocks from the | 4027 | * Get the # of file system overhead blocks from the |
4015 | * superblock if present. | 4028 | * superblock if present. |
@@ -5519,11 +5532,9 @@ static int __init ext4_init_fs(void) | |||
5519 | 5532 | ||
5520 | err = ext4_init_mballoc(); | 5533 | err = ext4_init_mballoc(); |
5521 | if (err) | 5534 | if (err) |
5522 | goto out3; | ||
5523 | |||
5524 | err = ext4_init_xattr(); | ||
5525 | if (err) | ||
5526 | goto out2; | 5535 | goto out2; |
5536 | else | ||
5537 | ext4_mballoc_ready = 1; | ||
5527 | err = init_inodecache(); | 5538 | err = init_inodecache(); |
5528 | if (err) | 5539 | if (err) |
5529 | goto out1; | 5540 | goto out1; |
@@ -5539,10 +5550,9 @@ out: | |||
5539 | unregister_as_ext3(); | 5550 | unregister_as_ext3(); |
5540 | destroy_inodecache(); | 5551 | destroy_inodecache(); |
5541 | out1: | 5552 | out1: |
5542 | ext4_exit_xattr(); | 5553 | ext4_mballoc_ready = 0; |
5543 | out2: | ||
5544 | ext4_exit_mballoc(); | 5554 | ext4_exit_mballoc(); |
5545 | out3: | 5555 | out2: |
5546 | ext4_exit_feat_adverts(); | 5556 | ext4_exit_feat_adverts(); |
5547 | out4: | 5557 | out4: |
5548 | if (ext4_proc_root) | 5558 | if (ext4_proc_root) |
@@ -5565,7 +5575,6 @@ static void __exit ext4_exit_fs(void) | |||
5565 | unregister_as_ext3(); | 5575 | unregister_as_ext3(); |
5566 | unregister_filesystem(&ext4_fs_type); | 5576 | unregister_filesystem(&ext4_fs_type); |
5567 | destroy_inodecache(); | 5577 | destroy_inodecache(); |
5568 | ext4_exit_xattr(); | ||
5569 | ext4_exit_mballoc(); | 5578 | ext4_exit_mballoc(); |
5570 | ext4_exit_feat_adverts(); | 5579 | ext4_exit_feat_adverts(); |
5571 | remove_proc_entry("fs/ext4", NULL); | 5580 | remove_proc_entry("fs/ext4", NULL); |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 185066f475f1..1f5cf5880718 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -81,7 +81,7 @@ | |||
81 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 81 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | static void ext4_xattr_cache_insert(struct buffer_head *); | 84 | static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *); |
85 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, | 85 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, |
86 | struct ext4_xattr_header *, | 86 | struct ext4_xattr_header *, |
87 | struct mb_cache_entry **); | 87 | struct mb_cache_entry **); |
@@ -90,8 +90,6 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *, | |||
90 | static int ext4_xattr_list(struct dentry *dentry, char *buffer, | 90 | static int ext4_xattr_list(struct dentry *dentry, char *buffer, |
91 | size_t buffer_size); | 91 | size_t buffer_size); |
92 | 92 | ||
93 | static struct mb_cache *ext4_xattr_cache; | ||
94 | |||
95 | static const struct xattr_handler *ext4_xattr_handler_map[] = { | 93 | static const struct xattr_handler *ext4_xattr_handler_map[] = { |
96 | [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, | 94 | [EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler, |
97 | #ifdef CONFIG_EXT4_FS_POSIX_ACL | 95 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
@@ -117,6 +115,9 @@ const struct xattr_handler *ext4_xattr_handlers[] = { | |||
117 | NULL | 115 | NULL |
118 | }; | 116 | }; |
119 | 117 | ||
118 | #define EXT4_GET_MB_CACHE(inode) (((struct ext4_sb_info *) \ | ||
119 | inode->i_sb->s_fs_info)->s_mb_cache) | ||
120 | |||
120 | static __le32 ext4_xattr_block_csum(struct inode *inode, | 121 | static __le32 ext4_xattr_block_csum(struct inode *inode, |
121 | sector_t block_nr, | 122 | sector_t block_nr, |
122 | struct ext4_xattr_header *hdr) | 123 | struct ext4_xattr_header *hdr) |
@@ -265,6 +266,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, | |||
265 | struct ext4_xattr_entry *entry; | 266 | struct ext4_xattr_entry *entry; |
266 | size_t size; | 267 | size_t size; |
267 | int error; | 268 | int error; |
269 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
268 | 270 | ||
269 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", | 271 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", |
270 | name_index, name, buffer, (long)buffer_size); | 272 | name_index, name, buffer, (long)buffer_size); |
@@ -286,7 +288,7 @@ bad_block: | |||
286 | error = -EIO; | 288 | error = -EIO; |
287 | goto cleanup; | 289 | goto cleanup; |
288 | } | 290 | } |
289 | ext4_xattr_cache_insert(bh); | 291 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
290 | entry = BFIRST(bh); | 292 | entry = BFIRST(bh); |
291 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); | 293 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); |
292 | if (error == -EIO) | 294 | if (error == -EIO) |
@@ -409,6 +411,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
409 | struct inode *inode = dentry->d_inode; | 411 | struct inode *inode = dentry->d_inode; |
410 | struct buffer_head *bh = NULL; | 412 | struct buffer_head *bh = NULL; |
411 | int error; | 413 | int error; |
414 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
412 | 415 | ||
413 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", | 416 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", |
414 | buffer, (long)buffer_size); | 417 | buffer, (long)buffer_size); |
@@ -430,7 +433,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
430 | error = -EIO; | 433 | error = -EIO; |
431 | goto cleanup; | 434 | goto cleanup; |
432 | } | 435 | } |
433 | ext4_xattr_cache_insert(bh); | 436 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
434 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); | 437 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); |
435 | 438 | ||
436 | cleanup: | 439 | cleanup: |
@@ -526,8 +529,9 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
526 | { | 529 | { |
527 | struct mb_cache_entry *ce = NULL; | 530 | struct mb_cache_entry *ce = NULL; |
528 | int error = 0; | 531 | int error = 0; |
532 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
529 | 533 | ||
530 | ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); | 534 | ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr); |
531 | error = ext4_journal_get_write_access(handle, bh); | 535 | error = ext4_journal_get_write_access(handle, bh); |
532 | if (error) | 536 | if (error) |
533 | goto out; | 537 | goto out; |
@@ -746,13 +750,14 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
746 | struct ext4_xattr_search *s = &bs->s; | 750 | struct ext4_xattr_search *s = &bs->s; |
747 | struct mb_cache_entry *ce = NULL; | 751 | struct mb_cache_entry *ce = NULL; |
748 | int error = 0; | 752 | int error = 0; |
753 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
749 | 754 | ||
750 | #define header(x) ((struct ext4_xattr_header *)(x)) | 755 | #define header(x) ((struct ext4_xattr_header *)(x)) |
751 | 756 | ||
752 | if (i->value && i->value_len > sb->s_blocksize) | 757 | if (i->value && i->value_len > sb->s_blocksize) |
753 | return -ENOSPC; | 758 | return -ENOSPC; |
754 | if (s->base) { | 759 | if (s->base) { |
755 | ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, | 760 | ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev, |
756 | bs->bh->b_blocknr); | 761 | bs->bh->b_blocknr); |
757 | error = ext4_journal_get_write_access(handle, bs->bh); | 762 | error = ext4_journal_get_write_access(handle, bs->bh); |
758 | if (error) | 763 | if (error) |
@@ -770,7 +775,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
770 | if (!IS_LAST_ENTRY(s->first)) | 775 | if (!IS_LAST_ENTRY(s->first)) |
771 | ext4_xattr_rehash(header(s->base), | 776 | ext4_xattr_rehash(header(s->base), |
772 | s->here); | 777 | s->here); |
773 | ext4_xattr_cache_insert(bs->bh); | 778 | ext4_xattr_cache_insert(ext4_mb_cache, |
779 | bs->bh); | ||
774 | } | 780 | } |
775 | unlock_buffer(bs->bh); | 781 | unlock_buffer(bs->bh); |
776 | if (error == -EIO) | 782 | if (error == -EIO) |
@@ -906,7 +912,7 @@ getblk_failed: | |||
906 | memcpy(new_bh->b_data, s->base, new_bh->b_size); | 912 | memcpy(new_bh->b_data, s->base, new_bh->b_size); |
907 | set_buffer_uptodate(new_bh); | 913 | set_buffer_uptodate(new_bh); |
908 | unlock_buffer(new_bh); | 914 | unlock_buffer(new_bh); |
909 | ext4_xattr_cache_insert(new_bh); | 915 | ext4_xattr_cache_insert(ext4_mb_cache, new_bh); |
910 | error = ext4_handle_dirty_xattr_block(handle, | 916 | error = ext4_handle_dirty_xattr_block(handle, |
911 | inode, new_bh); | 917 | inode, new_bh); |
912 | if (error) | 918 | if (error) |
@@ -1495,13 +1501,13 @@ ext4_xattr_put_super(struct super_block *sb) | |||
1495 | * Returns 0, or a negative error number on failure. | 1501 | * Returns 0, or a negative error number on failure. |
1496 | */ | 1502 | */ |
1497 | static void | 1503 | static void |
1498 | ext4_xattr_cache_insert(struct buffer_head *bh) | 1504 | ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh) |
1499 | { | 1505 | { |
1500 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); | 1506 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); |
1501 | struct mb_cache_entry *ce; | 1507 | struct mb_cache_entry *ce; |
1502 | int error; | 1508 | int error; |
1503 | 1509 | ||
1504 | ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS); | 1510 | ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS); |
1505 | if (!ce) { | 1511 | if (!ce) { |
1506 | ea_bdebug(bh, "out of memory"); | 1512 | ea_bdebug(bh, "out of memory"); |
1507 | return; | 1513 | return; |
@@ -1573,12 +1579,13 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header, | |||
1573 | { | 1579 | { |
1574 | __u32 hash = le32_to_cpu(header->h_hash); | 1580 | __u32 hash = le32_to_cpu(header->h_hash); |
1575 | struct mb_cache_entry *ce; | 1581 | struct mb_cache_entry *ce; |
1582 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
1576 | 1583 | ||
1577 | if (!header->h_hash) | 1584 | if (!header->h_hash) |
1578 | return NULL; /* never share */ | 1585 | return NULL; /* never share */ |
1579 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 1586 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |
1580 | again: | 1587 | again: |
1581 | ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev, | 1588 | ce = mb_cache_entry_find_first(ext4_mb_cache, inode->i_sb->s_bdev, |
1582 | hash); | 1589 | hash); |
1583 | while (ce) { | 1590 | while (ce) { |
1584 | struct buffer_head *bh; | 1591 | struct buffer_head *bh; |
@@ -1676,19 +1683,17 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *header, | |||
1676 | 1683 | ||
1677 | #undef BLOCK_HASH_SHIFT | 1684 | #undef BLOCK_HASH_SHIFT |
1678 | 1685 | ||
1679 | int __init | 1686 | #define HASH_BUCKET_BITS 10 |
1680 | ext4_init_xattr(void) | 1687 | |
1688 | struct mb_cache * | ||
1689 | ext4_xattr_create_cache(char *name) | ||
1681 | { | 1690 | { |
1682 | ext4_xattr_cache = mb_cache_create("ext4_xattr", 6); | 1691 | return mb_cache_create(name, HASH_BUCKET_BITS); |
1683 | if (!ext4_xattr_cache) | ||
1684 | return -ENOMEM; | ||
1685 | return 0; | ||
1686 | } | 1692 | } |
1687 | 1693 | ||
1688 | void | 1694 | void ext4_xattr_destroy_cache(struct mb_cache *cache) |
1689 | ext4_exit_xattr(void) | ||
1690 | { | 1695 | { |
1691 | if (ext4_xattr_cache) | 1696 | if (cache) |
1692 | mb_cache_destroy(ext4_xattr_cache); | 1697 | mb_cache_destroy(cache); |
1693 | ext4_xattr_cache = NULL; | ||
1694 | } | 1698 | } |
1699 | |||
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 819d6398833f..29bedf5589f6 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -110,9 +110,6 @@ extern void ext4_xattr_put_super(struct super_block *); | |||
110 | extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | 110 | extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, |
111 | struct ext4_inode *raw_inode, handle_t *handle); | 111 | struct ext4_inode *raw_inode, handle_t *handle); |
112 | 112 | ||
113 | extern int __init ext4_init_xattr(void); | ||
114 | extern void ext4_exit_xattr(void); | ||
115 | |||
116 | extern const struct xattr_handler *ext4_xattr_handlers[]; | 113 | extern const struct xattr_handler *ext4_xattr_handlers[]; |
117 | 114 | ||
118 | extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, | 115 | extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, |
@@ -124,6 +121,9 @@ extern int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode, | |||
124 | struct ext4_xattr_info *i, | 121 | struct ext4_xattr_info *i, |
125 | struct ext4_xattr_ibody_find *is); | 122 | struct ext4_xattr_ibody_find *is); |
126 | 123 | ||
124 | extern struct mb_cache *ext4_xattr_create_cache(char *name); | ||
125 | extern void ext4_xattr_destroy_cache(struct mb_cache *); | ||
126 | |||
127 | #ifdef CONFIG_EXT4_FS_SECURITY | 127 | #ifdef CONFIG_EXT4_FS_SECURITY |
128 | extern int ext4_init_security(handle_t *handle, struct inode *inode, | 128 | extern int ext4_init_security(handle_t *handle, struct inode *inode, |
129 | struct inode *dir, const struct qstr *qstr); | 129 | struct inode *dir, const struct qstr *qstr); |
diff --git a/fs/mbcache.c b/fs/mbcache.c index 786ecab81c99..bf166e388f0d 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -99,6 +99,7 @@ | |||
99 | 99 | ||
100 | static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue); | 100 | static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue); |
101 | static struct blockgroup_lock *mb_cache_bg_lock; | 101 | static struct blockgroup_lock *mb_cache_bg_lock; |
102 | static struct kmem_cache *mb_cache_kmem_cache; | ||
102 | 103 | ||
103 | MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>"); | 104 | MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>"); |
104 | MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); | 105 | MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); |
@@ -351,11 +352,14 @@ mb_cache_create(const char *name, int bucket_bits) | |||
351 | goto fail; | 352 | goto fail; |
352 | for (n=0; n<bucket_count; n++) | 353 | for (n=0; n<bucket_count; n++) |
353 | INIT_HLIST_BL_HEAD(&cache->c_index_hash[n]); | 354 | INIT_HLIST_BL_HEAD(&cache->c_index_hash[n]); |
354 | cache->c_entry_cache = kmem_cache_create(name, | 355 | if (!mb_cache_kmem_cache) { |
355 | sizeof(struct mb_cache_entry), 0, | 356 | mb_cache_kmem_cache = kmem_cache_create(name, |
356 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL); | 357 | sizeof(struct mb_cache_entry), 0, |
357 | if (!cache->c_entry_cache) | 358 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL); |
358 | goto fail2; | 359 | if (!mb_cache_kmem_cache) |
360 | goto fail2; | ||
361 | } | ||
362 | cache->c_entry_cache = mb_cache_kmem_cache; | ||
359 | 363 | ||
360 | /* | 364 | /* |
361 | * Set an upper limit on the number of cache entries so that the hash | 365 | * Set an upper limit on the number of cache entries so that the hash |
@@ -476,6 +480,10 @@ mb_cache_destroy(struct mb_cache *cache) | |||
476 | atomic_read(&cache->c_entry_count)); | 480 | atomic_read(&cache->c_entry_count)); |
477 | } | 481 | } |
478 | 482 | ||
483 | if (list_empty(&mb_cache_list)) { | ||
484 | kmem_cache_destroy(mb_cache_kmem_cache); | ||
485 | mb_cache_kmem_cache = NULL; | ||
486 | } | ||
479 | kfree(cache->c_index_hash); | 487 | kfree(cache->c_index_hash); |
480 | kfree(cache->c_block_hash); | 488 | kfree(cache->c_block_hash); |
481 | kfree(cache); | 489 | kfree(cache); |