aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/super.c25
-rw-r--r--fs/ext4/xattr.c51
-rw-r--r--fs/ext4/xattr.h6
-rw-r--r--fs/mbcache.c18
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;
59static struct ext4_lazy_init *ext4_li_info; 59static struct ext4_lazy_init *ext4_li_info;
60static struct mutex ext4_li_mtx; 60static struct mutex ext4_li_mtx;
61static struct ext4_features *ext4_feat; 61static struct ext4_features *ext4_feat;
62static int ext4_mballoc_ready;
62 63
63static int ext4_load_journal(struct super_block *, struct ext4_super_block *, 64static 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
4012no_journal: 4017no_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();
5541out1: 5552out1:
5542 ext4_exit_xattr(); 5553 ext4_mballoc_ready = 0;
5543out2:
5544 ext4_exit_mballoc(); 5554 ext4_exit_mballoc();
5545out3: 5555out2:
5546 ext4_exit_feat_adverts(); 5556 ext4_exit_feat_adverts();
5547out4: 5557out4:
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
84static void ext4_xattr_cache_insert(struct buffer_head *); 84static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *);
85static struct buffer_head *ext4_xattr_cache_find(struct inode *, 85static 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 *,
90static int ext4_xattr_list(struct dentry *dentry, char *buffer, 90static int ext4_xattr_list(struct dentry *dentry, char *buffer,
91 size_t buffer_size); 91 size_t buffer_size);
92 92
93static struct mb_cache *ext4_xattr_cache;
94
95static const struct xattr_handler *ext4_xattr_handler_map[] = { 93static 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
120static __le32 ext4_xattr_block_csum(struct inode *inode, 121static __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
436cleanup: 439cleanup:
@@ -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 */
1497static void 1503static void
1498ext4_xattr_cache_insert(struct buffer_head *bh) 1504ext4_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);
1580again: 1587again:
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
1679int __init 1686#define HASH_BUCKET_BITS 10
1680ext4_init_xattr(void) 1687
1688struct mb_cache *
1689ext4_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
1688void 1694void ext4_xattr_destroy_cache(struct mb_cache *cache)
1689ext4_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 *);
110extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, 110extern 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
113extern int __init ext4_init_xattr(void);
114extern void ext4_exit_xattr(void);
115
116extern const struct xattr_handler *ext4_xattr_handlers[]; 113extern const struct xattr_handler *ext4_xattr_handlers[];
117 114
118extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, 115extern 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
124extern struct mb_cache *ext4_xattr_create_cache(char *name);
125extern void ext4_xattr_destroy_cache(struct mb_cache *);
126
127#ifdef CONFIG_EXT4_FS_SECURITY 127#ifdef CONFIG_EXT4_FS_SECURITY
128extern int ext4_init_security(handle_t *handle, struct inode *inode, 128extern 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
100static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue); 100static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
101static struct blockgroup_lock *mb_cache_bg_lock; 101static struct blockgroup_lock *mb_cache_bg_lock;
102static struct kmem_cache *mb_cache_kmem_cache;
102 103
103MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>"); 104MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
104MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); 105MODULE_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);