add jbd2 speedup patches
[ext4-patch-queue.git] / each-fs-creates-its-own-mb_cache
blob63cc6c4dff250a602d0bb144067f53186b80b563
1 ext4: each filesystem creates and uses its own mb_cache
3 From: T Makphaibulchoke <tmac@hp.com>
5 This patch adds new interfaces to create and destory cache,
6 ext4_xattr_create_cache() and ext4_xattr_destroy_cache(), and remove
7 the cache creation and destory calls from ex4_init_xattr() and
8 ext4_exitxattr() in fs/ext4/xattr.c.  fs/ext4/super.c has been changed
9 so that when a filesystem is mounted a cache is allocated and attched
10 to its ext4_sb_info structure.
12 Signed-off-by: T. Makphaibulchoke <tmac@hp.com>
13 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
14 ---
15  fs/ext4/ext4.h          |  1 +
16  fs/ext4/super.c         | 37 ++++++++++++++++++++++++++++---------
17  fs/ext4/xattr.c         | 54 +++++++++++++++++++++++++++++++-----------------------
18  fs/ext4/xattr.h         |  8 +++++---
19  fs/mbcache.c            | 50 +++++++++++++++++++++++++++++++++++++-------------
20  include/linux/mbcache.h |  3 +++
21  6 files changed, 105 insertions(+), 48 deletions(-)
23 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
24 index 65485ab..c3d1993 100644
25 --- a/fs/ext4/ext4.h
26 +++ b/fs/ext4/ext4.h
27 @@ -1314,6 +1314,7 @@ struct ext4_sb_info {
28         struct list_head s_es_lru;
29         unsigned long s_es_last_sorted;
30         struct percpu_counter s_extent_cache_cnt;
31 +       struct mb_cache *s_mb_cache;
32         spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
34         /* Ratelimit ext4 messages. */
35 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
36 index d3a857b..d529807 100644
37 --- a/fs/ext4/super.c
38 +++ b/fs/ext4/super.c
39 @@ -31,6 +31,7 @@
40  #include <linux/vfs.h>
41  #include <linux/random.h>
42  #include <linux/mount.h>
43 +#include <linux/mbcache.h>
44  #include <linux/namei.h>
45  #include <linux/quotaops.h>
46  #include <linux/seq_file.h>
47 @@ -59,6 +60,7 @@ static struct kset *ext4_kset;
48  static struct ext4_lazy_init *ext4_li_info;
49  static struct mutex ext4_li_mtx;
50  static struct ext4_features *ext4_feat;
51 +static int ext4_mballoc_ready;
53  static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
54                              unsigned long journal_devnum);
55 @@ -845,6 +847,10 @@ static void ext4_put_super(struct super_block *sb)
56                 invalidate_bdev(sbi->journal_bdev);
57                 ext4_blkdev_remove(sbi);
58         }
59 +       if (sbi->s_mb_cache) {
60 +               ext4_xattr_destroy_cache(sbi->s_mb_cache);
61 +               sbi->s_mb_cache = NULL;
62 +       }
63         if (sbi->s_mmp_tsk)
64                 kthread_stop(sbi->s_mmp_tsk);
65         sb->s_fs_info = NULL;
66 @@ -3984,6 +3990,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
67         set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
69         sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
70 +       if (ext4_mballoc_ready) {
71 +               sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id);
72 +               if (!sbi->s_mb_cache) {
73 +                       ext4_msg(sb, KERN_ERR, "Failed to create an mb_cache");
74 +                       goto failed_mount_wq;
75 +               }
76 +       }
78         /*
79          * The journal may have updated the bg summary counts, so we
80 @@ -5480,9 +5493,16 @@ static int __init ext4_init_fs(void)
81                 init_waitqueue_head(&ext4__ioend_wq[i]);
82         }
84 +       ext4_xattr_kmem_cache = kmem_cache_create("ext4_xattr",
85 +               sizeof(struct mb_cache_entry), 0,
86 +               SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
87 +       if (ext4_xattr_kmem_cache == NULL)
88 +               return -ENOMEM;
91         err = ext4_init_es();
92         if (err)
93 -               return err;
94 +               goto out8;
96         err = ext4_init_pageio();
97         if (err)
98 @@ -5504,11 +5524,9 @@ static int __init ext4_init_fs(void)
100         err = ext4_init_mballoc();
101         if (err)
102 -               goto out3;
104 -       err = ext4_init_xattr();
105 -       if (err)
106                 goto out2;
107 +       else
108 +               ext4_mballoc_ready = 1;
109         err = init_inodecache();
110         if (err)
111                 goto out1;
112 @@ -5524,10 +5542,9 @@ out:
113         unregister_as_ext3();
114         destroy_inodecache();
115  out1:
116 -       ext4_exit_xattr();
117 -out2:
118 +       ext4_mballoc_ready = 0;
119         ext4_exit_mballoc();
120 -out3:
121 +out2:
122         ext4_exit_feat_adverts();
123  out4:
124         if (ext4_proc_root)
125 @@ -5539,18 +5556,20 @@ out6:
126         ext4_exit_pageio();
127  out7:
128         ext4_exit_es();
129 +out8:
130 +       kmem_cache_destroy(ext4_xattr_kmem_cache);
132         return err;
135  static void __exit ext4_exit_fs(void)
137 +       kmem_cache_destroy(ext4_xattr_kmem_cache);
138         ext4_destroy_lazyinit_thread();
139         unregister_as_ext2();
140         unregister_as_ext3();
141         unregister_filesystem(&ext4_fs_type);
142         destroy_inodecache();
143 -       ext4_exit_xattr();
144         ext4_exit_mballoc();
145         ext4_exit_feat_adverts();
146         remove_proc_entry("fs/ext4", NULL);
147 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
148 index 03e9beb..3d2bd5a 100644
149 --- a/fs/ext4/xattr.c
150 +++ b/fs/ext4/xattr.c
151 @@ -81,7 +81,9 @@
152  # define ea_bdebug(bh, fmt, ...)       no_printk(fmt, ##__VA_ARGS__)
153  #endif
155 -static void ext4_xattr_cache_insert(struct buffer_head *);
156 +struct kmem_cache *ext4_xattr_kmem_cache;
158 +static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *);
159  static struct buffer_head *ext4_xattr_cache_find(struct inode *,
160                                                  struct ext4_xattr_header *,
161                                                  struct mb_cache_entry **);
162 @@ -90,8 +92,6 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *,
163  static int ext4_xattr_list(struct dentry *dentry, char *buffer,
164                            size_t buffer_size);
166 -static struct mb_cache *ext4_xattr_cache;
168  static const struct xattr_handler *ext4_xattr_handler_map[] = {
169         [EXT4_XATTR_INDEX_USER]              = &ext4_xattr_user_handler,
170  #ifdef CONFIG_EXT4_FS_POSIX_ACL
171 @@ -117,6 +117,9 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
172         NULL
173  };
175 +#define EXT4_GET_MB_CACHE(inode)       (((struct ext4_sb_info *) \
176 +                               inode->i_sb->s_fs_info)->s_mb_cache)
178  static __le32 ext4_xattr_block_csum(struct inode *inode,
179                                     sector_t block_nr,
180                                     struct ext4_xattr_header *hdr)
181 @@ -265,6 +268,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
182         struct ext4_xattr_entry *entry;
183         size_t size;
184         int error;
185 +       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
187         ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
188                   name_index, name, buffer, (long)buffer_size);
189 @@ -286,7 +290,7 @@ bad_block:
190                 error = -EIO;
191                 goto cleanup;
192         }
193 -       ext4_xattr_cache_insert(bh);
194 +       ext4_xattr_cache_insert(ext4_mb_cache, bh);
195         entry = BFIRST(bh);
196         error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
197         if (error == -EIO)
198 @@ -409,6 +413,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
199         struct inode *inode = dentry->d_inode;
200         struct buffer_head *bh = NULL;
201         int error;
202 +       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
204         ea_idebug(inode, "buffer=%p, buffer_size=%ld",
205                   buffer, (long)buffer_size);
206 @@ -430,7 +435,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
207                 error = -EIO;
208                 goto cleanup;
209         }
210 -       ext4_xattr_cache_insert(bh);
211 +       ext4_xattr_cache_insert(ext4_mb_cache, bh);
212         error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
214  cleanup:
215 @@ -526,8 +531,9 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
217         struct mb_cache_entry *ce = NULL;
218         int error = 0;
219 +       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
221 -       ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
222 +       ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr);
223         error = ext4_journal_get_write_access(handle, bh);
224         if (error)
225                 goto out;
226 @@ -745,13 +751,14 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
227         struct ext4_xattr_search *s = &bs->s;
228         struct mb_cache_entry *ce = NULL;
229         int error = 0;
230 +       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
232  #define header(x) ((struct ext4_xattr_header *)(x))
234         if (i->value && i->value_len > sb->s_blocksize)
235                 return -ENOSPC;
236         if (s->base) {
237 -               ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
238 +               ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev,
239                                         bs->bh->b_blocknr);
240                 error = ext4_journal_get_write_access(handle, bs->bh);
241                 if (error)
242 @@ -769,7 +776,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
243                                 if (!IS_LAST_ENTRY(s->first))
244                                         ext4_xattr_rehash(header(s->base),
245                                                           s->here);
246 -                               ext4_xattr_cache_insert(bs->bh);
247 +                               ext4_xattr_cache_insert(ext4_mb_cache,
248 +                                       bs->bh);
249                         }
250                         unlock_buffer(bs->bh);
251                         if (error == -EIO)
252 @@ -905,7 +913,7 @@ getblk_failed:
253                         memcpy(new_bh->b_data, s->base, new_bh->b_size);
254                         set_buffer_uptodate(new_bh);
255                         unlock_buffer(new_bh);
256 -                       ext4_xattr_cache_insert(new_bh);
257 +                       ext4_xattr_cache_insert(ext4_mb_cache, new_bh);
258                         error = ext4_handle_dirty_xattr_block(handle,
259                                                               inode, new_bh);
260                         if (error)
261 @@ -1494,13 +1502,13 @@ ext4_xattr_put_super(struct super_block *sb)
262   * Returns 0, or a negative error number on failure.
263   */
264  static void
265 -ext4_xattr_cache_insert(struct buffer_head *bh)
266 +ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh)
268         __u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
269         struct mb_cache_entry *ce;
270         int error;
272 -       ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS);
273 +       ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS);
274         if (!ce) {
275                 ea_bdebug(bh, "out of memory");
276                 return;
277 @@ -1572,12 +1580,13 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header,
279         __u32 hash = le32_to_cpu(header->h_hash);
280         struct mb_cache_entry *ce;
281 +       struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
283         if (!header->h_hash)
284                 return NULL;  /* never share */
285         ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
286  again:
287 -       ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev,
288 +       ce = mb_cache_entry_find_first(ext4_mb_cache, inode->i_sb->s_bdev,
289                                        hash);
290         while (ce) {
291                 struct buffer_head *bh;
292 @@ -1675,19 +1684,18 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *header,
294  #undef BLOCK_HASH_SHIFT
296 -int __init
297 -ext4_init_xattr(void)
298 +#define        HASH_BUCKET_BITS        6
300 +struct mb_cache *
301 +ext4_xattr_create_cache(char *name)
303 -       ext4_xattr_cache = mb_cache_create("ext4_xattr", 6);
304 -       if (!ext4_xattr_cache)
305 -               return -ENOMEM;
306 -       return 0;
307 +       return mb_cache_create_instance(name, HASH_BUCKET_BITS,
308 +                                       ext4_xattr_kmem_cache);
311 -void
312 -ext4_exit_xattr(void)
313 +void ext4_xattr_destroy_cache(struct mb_cache *cache)
315 -       if (ext4_xattr_cache)
316 -               mb_cache_destroy(ext4_xattr_cache);
317 -       ext4_xattr_cache = NULL;
318 +       if (cache)
319 +               mb_cache_destroy(cache);
322 diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
323 index c767dbd..15616eb 100644
324 --- a/fs/ext4/xattr.h
325 +++ b/fs/ext4/xattr.h
326 @@ -94,6 +94,8 @@ struct ext4_xattr_ibody_find {
327         struct ext4_iloc iloc;
328  };
330 +extern struct kmem_cache *ext4_xattr_kmem_cache;
332  extern const struct xattr_handler ext4_xattr_user_handler;
333  extern const struct xattr_handler ext4_xattr_trusted_handler;
334  extern const struct xattr_handler ext4_xattr_acl_access_handler;
335 @@ -112,9 +114,6 @@ extern void ext4_xattr_put_super(struct super_block *);
336  extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
337                             struct ext4_inode *raw_inode, handle_t *handle);
339 -extern int __init ext4_init_xattr(void);
340 -extern void ext4_exit_xattr(void);
342  extern const struct xattr_handler *ext4_xattr_handlers[];
344  extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
345 @@ -126,6 +125,9 @@ extern int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode,
346                                        struct ext4_xattr_info *i,
347                                        struct ext4_xattr_ibody_find *is);
349 +extern struct mb_cache *ext4_xattr_create_cache(char *name);
350 +extern void ext4_xattr_destroy_cache(struct mb_cache *);
352  #ifdef CONFIG_EXT4_FS_SECURITY
353  extern int ext4_init_security(handle_t *handle, struct inode *inode,
354                               struct inode *dir, const struct qstr *qstr);
355 diff --git a/fs/mbcache.c b/fs/mbcache.c
356 index 44e7153..8e373c6 100644
357 --- a/fs/mbcache.c
358 +++ b/fs/mbcache.c
359 @@ -96,6 +96,7 @@ MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
360  MODULE_LICENSE("GPL");
362  EXPORT_SYMBOL(mb_cache_create);
363 +EXPORT_SYMBOL(mb_cache_create_instance);
364  EXPORT_SYMBOL(mb_cache_shrink);
365  EXPORT_SYMBOL(mb_cache_destroy);
366  EXPORT_SYMBOL(mb_cache_entry_alloc);
367 @@ -260,18 +261,20 @@ static struct shrinker mb_cache_shrinker = {
368  };
370  /*
371 - * mb_cache_create()  create a new cache
372 + * mb_cache_create_instance()  create a new cache for a device
373   *
374   * All entries in one cache are equal size. Cache entries may be from
375 - * multiple devices. If this is the first mbcache created, registers
376 - * the cache with kernel memory management. Returns NULL if no more
377 + * multiple devices.  The caller must create a kmem_cache appropriate
378 + * for allocating struct mb_cache_entry.  Returns NULL if no more
379   * memory was available.
380   *
381   * @name: name of the cache (informal)
382   * @bucket_bits: log2(number of hash buckets)
383 + * @mb_kmem_cache: slab cache for mb_cache_entry structures
384   */
385  struct mb_cache *
386 -mb_cache_create(const char *name, int bucket_bits)
387 +mb_cache_create_instance(const char *name, int bucket_bits,
388 +                        struct kmem_cache *mb_kmem_cache)
390         int n, bucket_count = 1 << bucket_bits;
391         struct mb_cache *cache = NULL;
392 @@ -294,11 +297,8 @@ mb_cache_create(const char *name, int bucket_bits)
393                 goto fail;
394         for (n=0; n<bucket_count; n++)
395                 INIT_HLIST_BL_HEAD(&cache->c_index_hash[n]);
396 -       cache->c_entry_cache = kmem_cache_create(name,
397 -               sizeof(struct mb_cache_entry), 0,
398 -               SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
399 -       if (!cache->c_entry_cache)
400 -               goto fail2;
401 +       BUG_ON(mb_kmem_cache == NULL);
402 +       cache->c_entry_cache = mb_kmem_cache;
404         /*
405          * Set an upper limit on the number of cache entries so that the hash
406 @@ -311,15 +311,38 @@ mb_cache_create(const char *name, int bucket_bits)
407         spin_unlock(&mb_cache_spinlock);
408         return cache;
410 -fail2:
411 -       kfree(cache->c_index_hash);
413  fail:
414         kfree(cache->c_block_hash);
415         kfree(cache);
416         return NULL;
420 + * mb_cache_create()  create a new cache
421 + *
422 + * All entries in one cache are equal size. Cache entries may be from
423 + * multiple devices.  Returns NULL if no more memory was available.
424 + *
425 + * @name: name of the cache (informal)
426 + * @bucket_bits: log2(number of hash buckets)
427 + */
428 +struct mb_cache *
429 +mb_cache_create(const char *name, int bucket_bits)
431 +       struct kmem_cache *mb_kmem_cache;
432 +       struct mb_cache *cache;
434 +       mb_kmem_cache = kmem_cache_create(name,
435 +               sizeof(struct mb_cache_entry), 0,
436 +               SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
437 +       if (mb_kmem_cache == NULL)
438 +               return NULL;
439 +       cache = mb_cache_create_instance(name, bucket_bits, mb_kmem_cache); 
440 +       if (cache == NULL)
441 +               kmem_cache_destroy(mb_kmem_cache);
442 +       cache->c_entry_cache_autofree = 1;
443 +       return cache;
446  /*
447   * mb_cache_shrink()
448 @@ -406,7 +429,8 @@ mb_cache_destroy(struct mb_cache *cache)
449                           atomic_read(&cache->c_entry_count));
450         }
452 -       kmem_cache_destroy(cache->c_entry_cache);
453 +       if (cache->c_entry_cache_autofree)
454 +               kmem_cache_destroy(cache->c_entry_cache);
456         kfree(cache->c_index_hash);
457         kfree(cache->c_block_hash);
458 diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h
459 index 89826c0..b326ce7 100644
460 --- a/include/linux/mbcache.h
461 +++ b/include/linux/mbcache.h
462 @@ -29,11 +29,14 @@ struct mb_cache {
463         struct kmem_cache               *c_entry_cache;
464         struct hlist_bl_head            *c_block_hash;
465         struct hlist_bl_head            *c_index_hash;
466 +       unsigned int                    c_entry_cache_autofree:1;
467  };
469  /* Functions on caches */
471  struct mb_cache *mb_cache_create(const char *, int);
472 +struct mb_cache *mb_cache_create_instance(const char *,
473 +                                         int, struct kmem_cache *);
474  void mb_cache_shrink(struct block_device *);
475  void mb_cache_destroy(struct mb_cache *);