add patch return-hole-from-ext4_map_blocks
[ext4-patch-queue.git] / ext2-convert-to-mbcache2
blobd98d417b6c96c148241f7c87093345356012b803
1 ext2: convert to mbcache2
3 From: Jan Kara <jack@suse.cz>
5 The conversion is generally straightforward. We convert filesystem from
6 a global cache to per-fs one. Similarly to ext4 the tricky part is that
7 xattr block corresponding to found mbcache entry can get freed before we
8 get buffer lock for that block. So we have to check whether the entry is
9 still valid after getting the buffer lock.
11 Signed-off-by: Jan Kara <jack@suse.cz>
12 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 ---
14  fs/ext2/ext2.h  |   3 ++
15  fs/ext2/super.c |  25 ++++++----
16  fs/ext2/xattr.c | 143 ++++++++++++++++++++++++++------------------------------
17  fs/ext2/xattr.h |  21 ++-------
18  4 files changed, 92 insertions(+), 100 deletions(-)
20 diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
21 index 4c69c94cafd8..f98ce7e60a0f 100644
22 --- a/fs/ext2/ext2.h
23 +++ b/fs/ext2/ext2.h
24 @@ -61,6 +61,8 @@ struct ext2_block_alloc_info {
25  #define rsv_start rsv_window._rsv_start
26  #define rsv_end rsv_window._rsv_end
28 +struct mb2_cache;
30  /*
31   * second extended-fs super-block data in memory
32   */
33 @@ -111,6 +113,7 @@ struct ext2_sb_info {
34          * of the mount options.
35          */
36         spinlock_t s_lock;
37 +       struct mb2_cache *s_mb_cache;
38  };
40  static inline spinlock_t *
41 diff --git a/fs/ext2/super.c b/fs/ext2/super.c
42 index 2a188413a2b0..b78caf25f746 100644
43 --- a/fs/ext2/super.c
44 +++ b/fs/ext2/super.c
45 @@ -131,7 +131,10 @@ static void ext2_put_super (struct super_block * sb)
47         dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
49 -       ext2_xattr_put_super(sb);
50 +       if (sbi->s_mb_cache) {
51 +               ext2_xattr_destroy_cache(sbi->s_mb_cache);
52 +               sbi->s_mb_cache = NULL;
53 +       }
54         if (!(sb->s_flags & MS_RDONLY)) {
55                 struct ext2_super_block *es = sbi->s_es;
57 @@ -1104,6 +1107,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
58                 ext2_msg(sb, KERN_ERR, "error: insufficient memory");
59                 goto failed_mount3;
60         }
62 +#ifdef CONFIG_EXT2_FS_XATTR
63 +       sbi->s_mb_cache = ext2_xattr_create_cache();
64 +       if (!sbi->s_mb_cache) {
65 +               ext2_msg(sb, KERN_ERR, "Failed to create an mb_cache");
66 +               goto failed_mount3;
67 +       }
68 +#endif
69         /*
70          * set up enough so that it can read an inode
71          */
72 @@ -1149,6 +1160,8 @@ cantfind_ext2:
73                         sb->s_id);
74         goto failed_mount;
75  failed_mount3:
76 +       if (sbi->s_mb_cache)
77 +               ext2_xattr_destroy_cache(sbi->s_mb_cache);
78         percpu_counter_destroy(&sbi->s_freeblocks_counter);
79         percpu_counter_destroy(&sbi->s_freeinodes_counter);
80         percpu_counter_destroy(&sbi->s_dirs_counter);
81 @@ -1555,20 +1568,17 @@ MODULE_ALIAS_FS("ext2");
83  static int __init init_ext2_fs(void)
84  {
85 -       int err = init_ext2_xattr();
86 -       if (err)
87 -               return err;
88 +       int err;
90         err = init_inodecache();
91         if (err)
92 -               goto out1;
93 +               return err;
94          err = register_filesystem(&ext2_fs_type);
95         if (err)
96                 goto out;
97         return 0;
98  out:
99         destroy_inodecache();
100 -out1:
101 -       exit_ext2_xattr();
102         return err;
105 @@ -1576,7 +1586,6 @@ static void __exit exit_ext2_fs(void)
107         unregister_filesystem(&ext2_fs_type);
108         destroy_inodecache();
109 -       exit_ext2_xattr();
112  MODULE_AUTHOR("Remy Card and others");
113 diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
114 index f57a7aba32eb..7162b4869bc3 100644
115 --- a/fs/ext2/xattr.c
116 +++ b/fs/ext2/xattr.c
117 @@ -56,7 +56,7 @@
118  #include <linux/buffer_head.h>
119  #include <linux/init.h>
120  #include <linux/slab.h>
121 -#include <linux/mbcache.h>
122 +#include <linux/mbcache2.h>
123  #include <linux/quotaops.h>
124  #include <linux/rwsem.h>
125  #include <linux/security.h>
126 @@ -90,14 +90,12 @@
127  static int ext2_xattr_set2(struct inode *, struct buffer_head *,
128                            struct ext2_xattr_header *);
130 -static int ext2_xattr_cache_insert(struct buffer_head *);
131 +static int ext2_xattr_cache_insert(struct mb2_cache *, struct buffer_head *);
132  static struct buffer_head *ext2_xattr_cache_find(struct inode *,
133                                                  struct ext2_xattr_header *);
134  static void ext2_xattr_rehash(struct ext2_xattr_header *,
135                               struct ext2_xattr_entry *);
137 -static struct mb_cache *ext2_xattr_cache;
139  static const struct xattr_handler *ext2_xattr_handler_map[] = {
140         [EXT2_XATTR_INDEX_USER]              = &ext2_xattr_user_handler,
141  #ifdef CONFIG_EXT2_FS_POSIX_ACL
142 @@ -152,6 +150,7 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
143         size_t name_len, size;
144         char *end;
145         int error;
146 +       struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
148         ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
149                   name_index, name, buffer, (long)buffer_size);
150 @@ -196,7 +195,7 @@ bad_block:  ext2_error(inode->i_sb, "ext2_xattr_get",
151                         goto found;
152                 entry = next;
153         }
154 -       if (ext2_xattr_cache_insert(bh))
155 +       if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
156                 ea_idebug(inode, "cache insert failed");
157         error = -ENODATA;
158         goto cleanup;
159 @@ -209,7 +208,7 @@ found:
160             le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
161                 goto bad_block;
163 -       if (ext2_xattr_cache_insert(bh))
164 +       if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
165                 ea_idebug(inode, "cache insert failed");
166         if (buffer) {
167                 error = -ERANGE;
168 @@ -247,6 +246,7 @@ ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
169         char *end;
170         size_t rest = buffer_size;
171         int error;
172 +       struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
174         ea_idebug(inode, "buffer=%p, buffer_size=%ld",
175                   buffer, (long)buffer_size);
176 @@ -281,7 +281,7 @@ bad_block:  ext2_error(inode->i_sb, "ext2_xattr_list",
177                         goto bad_block;
178                 entry = next;
179         }
180 -       if (ext2_xattr_cache_insert(bh))
181 +       if (ext2_xattr_cache_insert(ext2_mb_cache, bh))
182                 ea_idebug(inode, "cache insert failed");
184         /* list the attribute names */
185 @@ -483,22 +483,23 @@ bad_block:                ext2_error(sb, "ext2_xattr_set",
186         /* Here we know that we can set the new attribute. */
188         if (header) {
189 -               struct mb_cache_entry *ce;
191                 /* assert(header == HDR(bh)); */
192 -               ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_bdev,
193 -                                       bh->b_blocknr);
194                 lock_buffer(bh);
195                 if (header->h_refcount == cpu_to_le32(1)) {
196 +                       __u32 hash = le32_to_cpu(header->h_hash);
198                         ea_bdebug(bh, "modifying in-place");
199 -                       if (ce)
200 -                               mb_cache_entry_free(ce);
201 +                       /*
202 +                        * This must happen under buffer lock for
203 +                        * ext2_xattr_set2() to reliably detect modified block
204 +                        */
205 +                       mb2_cache_entry_delete_block(EXT2_SB(sb)->s_mb_cache,
206 +                                                    hash, bh->b_blocknr);
208                         /* keep the buffer locked while modifying it. */
209                 } else {
210                         int offset;
212 -                       if (ce)
213 -                               mb_cache_entry_release(ce);
214                         unlock_buffer(bh);
215                         ea_bdebug(bh, "cloning");
216                         header = kmalloc(bh->b_size, GFP_KERNEL);
217 @@ -626,6 +627,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
218         struct super_block *sb = inode->i_sb;
219         struct buffer_head *new_bh = NULL;
220         int error;
221 +       struct mb2_cache *ext2_mb_cache = EXT2_SB(sb)->s_mb_cache;
223         if (header) {
224                 new_bh = ext2_xattr_cache_find(inode, header);
225 @@ -653,7 +655,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
226                            don't need to change the reference count. */
227                         new_bh = old_bh;
228                         get_bh(new_bh);
229 -                       ext2_xattr_cache_insert(new_bh);
230 +                       ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
231                 } else {
232                         /* We need to allocate a new block */
233                         ext2_fsblk_t goal = ext2_group_first_block_no(sb,
234 @@ -674,7 +676,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
235                         memcpy(new_bh->b_data, header, new_bh->b_size);
236                         set_buffer_uptodate(new_bh);
237                         unlock_buffer(new_bh);
238 -                       ext2_xattr_cache_insert(new_bh);
239 +                       ext2_xattr_cache_insert(ext2_mb_cache, new_bh);
240                         
241                         ext2_xattr_update_super_block(sb);
242                 }
243 @@ -707,19 +709,21 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
245         error = 0;
246         if (old_bh && old_bh != new_bh) {
247 -               struct mb_cache_entry *ce;
249                 /*
250                  * If there was an old block and we are no longer using it,
251                  * release the old block.
252                  */
253 -               ce = mb_cache_entry_get(ext2_xattr_cache, old_bh->b_bdev,
254 -                                       old_bh->b_blocknr);
255                 lock_buffer(old_bh);
256                 if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
257 +                       __u32 hash = le32_to_cpu(HDR(old_bh)->h_hash);
259 +                       /*
260 +                        * This must happen under buffer lock for
261 +                        * ext2_xattr_set2() to reliably detect freed block
262 +                        */
263 +                       mb2_cache_entry_delete_block(ext2_mb_cache,
264 +                                                    hash, old_bh->b_blocknr);
265                         /* Free the old block. */
266 -                       if (ce)
267 -                               mb_cache_entry_free(ce);
268                         ea_bdebug(old_bh, "freeing");
269                         ext2_free_blocks(inode, old_bh->b_blocknr, 1);
270                         mark_inode_dirty(inode);
271 @@ -730,8 +734,6 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
272                 } else {
273                         /* Decrement the refcount only. */
274                         le32_add_cpu(&HDR(old_bh)->h_refcount, -1);
275 -                       if (ce)
276 -                               mb_cache_entry_release(ce);
277                         dquot_free_block_nodirty(inode, 1);
278                         mark_inode_dirty(inode);
279                         mark_buffer_dirty(old_bh);
280 @@ -757,7 +759,6 @@ void
281  ext2_xattr_delete_inode(struct inode *inode)
283         struct buffer_head *bh = NULL;
284 -       struct mb_cache_entry *ce;
286         down_write(&EXT2_I(inode)->xattr_sem);
287         if (!EXT2_I(inode)->i_file_acl)
288 @@ -777,19 +778,22 @@ ext2_xattr_delete_inode(struct inode *inode)
289                         EXT2_I(inode)->i_file_acl);
290                 goto cleanup;
291         }
292 -       ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_bdev, bh->b_blocknr);
293         lock_buffer(bh);
294         if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
295 -               if (ce)
296 -                       mb_cache_entry_free(ce);
297 +               __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
299 +               /*
300 +                * This must happen under buffer lock for ext2_xattr_set2() to
301 +                * reliably detect freed block
302 +                */
303 +               mb2_cache_entry_delete_block(EXT2_SB(inode->i_sb)->s_mb_cache,
304 +                                            hash, bh->b_blocknr);
305                 ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
306                 get_bh(bh);
307                 bforget(bh);
308                 unlock_buffer(bh);
309         } else {
310                 le32_add_cpu(&HDR(bh)->h_refcount, -1);
311 -               if (ce)
312 -                       mb_cache_entry_release(ce);
313                 ea_bdebug(bh, "refcount now=%d",
314                         le32_to_cpu(HDR(bh)->h_refcount));
315                 unlock_buffer(bh);
316 @@ -806,18 +810,6 @@ cleanup:
319  /*
320 - * ext2_xattr_put_super()
321 - *
322 - * This is called when a file system is unmounted.
323 - */
324 -void
325 -ext2_xattr_put_super(struct super_block *sb)
327 -       mb_cache_shrink(sb->s_bdev);
332   * ext2_xattr_cache_insert()
333   *
334   * Create a new entry in the extended attribute cache, and insert
335 @@ -826,28 +818,20 @@ ext2_xattr_put_super(struct super_block *sb)
336   * Returns 0, or a negative error number on failure.
337   */
338  static int
339 -ext2_xattr_cache_insert(struct buffer_head *bh)
340 +ext2_xattr_cache_insert(struct mb2_cache *cache, struct buffer_head *bh)
342         __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
343 -       struct mb_cache_entry *ce;
344         int error;
346 -       ce = mb_cache_entry_alloc(ext2_xattr_cache, GFP_NOFS);
347 -       if (!ce)
348 -               return -ENOMEM;
349 -       error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash);
350 +       error = mb2_cache_entry_create(cache, GFP_NOFS, hash, bh->b_blocknr);
351         if (error) {
352 -               mb_cache_entry_free(ce);
353                 if (error == -EBUSY) {
354                         ea_bdebug(bh, "already in cache (%d cache entries)",
355                                 atomic_read(&ext2_xattr_cache->c_entry_count));
356                         error = 0;
357                 }
358 -       } else {
359 -               ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
360 -                         atomic_read(&ext2_xattr_cache->c_entry_count));
361 -               mb_cache_entry_release(ce);
362 -       }
363 +       } else
364 +               ea_bdebug(bh, "inserting [%x]", (int)hash);
365         return error;
368 @@ -903,23 +887,17 @@ static struct buffer_head *
369  ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
371         __u32 hash = le32_to_cpu(header->h_hash);
372 -       struct mb_cache_entry *ce;
373 +       struct mb2_cache_entry *ce;
374 +       struct mb2_cache *ext2_mb_cache = EXT2_SB(inode->i_sb)->s_mb_cache;
376         if (!header->h_hash)
377                 return NULL;  /* never share */
378         ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
379  again:
380 -       ce = mb_cache_entry_find_first(ext2_xattr_cache, inode->i_sb->s_bdev,
381 -                                      hash);
382 +       ce = mb2_cache_entry_find_first(ext2_mb_cache, hash);
383         while (ce) {
384                 struct buffer_head *bh;
386 -               if (IS_ERR(ce)) {
387 -                       if (PTR_ERR(ce) == -EAGAIN)
388 -                               goto again;
389 -                       break;
390 -               }
392                 bh = sb_bread(inode->i_sb, ce->e_block);
393                 if (!bh) {
394                         ext2_error(inode->i_sb, "ext2_xattr_cache_find",
395 @@ -927,7 +905,21 @@ again:
396                                 inode->i_ino, (unsigned long) ce->e_block);
397                 } else {
398                         lock_buffer(bh);
399 -                       if (le32_to_cpu(HDR(bh)->h_refcount) >
400 +                       /*
401 +                        * We have to be careful about races with freeing or
402 +                        * rehashing of xattr block. Once we hold buffer lock
403 +                        * xattr block's state is stable so we can check
404 +                        * whether the block got freed / rehashed or not.
405 +                        * Since we unhash mbcache entry under buffer lock when
406 +                        * freeing / rehashing xattr block, checking whether
407 +                        * entry is still hashed is reliable.
408 +                        */
409 +                       if (hlist_bl_unhashed(&ce->e_hash_list)) {
410 +                               mb2_cache_entry_put(ext2_mb_cache, ce);
411 +                               unlock_buffer(bh);
412 +                               brelse(bh);
413 +                               goto again;
414 +                       } else if (le32_to_cpu(HDR(bh)->h_refcount) >
415                                    EXT2_XATTR_REFCOUNT_MAX) {
416                                 ea_idebug(inode, "block %ld refcount %d>%d",
417                                           (unsigned long) ce->e_block,
418 @@ -936,13 +928,14 @@ again:
419                         } else if (!ext2_xattr_cmp(header, HDR(bh))) {
420                                 ea_bdebug(bh, "b_count=%d",
421                                           atomic_read(&(bh->b_count)));
422 -                               mb_cache_entry_release(ce);
423 +                               mb2_cache_entry_touch(ext2_mb_cache, ce);
424 +                               mb2_cache_entry_put(ext2_mb_cache, ce);
425                                 return bh;
426                         }
427                         unlock_buffer(bh);
428                         brelse(bh);
429                 }
430 -               ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash);
431 +               ce = mb2_cache_entry_find_next(ext2_mb_cache, ce);
432         }
433         return NULL;
435 @@ -1015,17 +1008,15 @@ static void ext2_xattr_rehash(struct ext2_xattr_header *header,
437  #undef BLOCK_HASH_SHIFT
439 -int __init
440 -init_ext2_xattr(void)
441 +#define HASH_BUCKET_BITS 10
443 +struct mb2_cache *ext2_xattr_create_cache(void)
445 -       ext2_xattr_cache = mb_cache_create("ext2_xattr", 6);
446 -       if (!ext2_xattr_cache)
447 -               return -ENOMEM;
448 -       return 0;
449 +       return mb2_cache_create(HASH_BUCKET_BITS);
452 -void
453 -exit_ext2_xattr(void)
454 +void ext2_xattr_destroy_cache(struct mb2_cache *cache)
456 -       mb_cache_destroy(ext2_xattr_cache);
457 +       if (cache)
458 +               mb2_cache_destroy(cache);
460 diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
461 index 60edf298644e..6ea38aa9563a 100644
462 --- a/fs/ext2/xattr.h
463 +++ b/fs/ext2/xattr.h
464 @@ -53,6 +53,8 @@ struct ext2_xattr_entry {
465  #define EXT2_XATTR_SIZE(size) \
466         (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
468 +struct mb2_cache;
470  # ifdef CONFIG_EXT2_FS_XATTR
472  extern const struct xattr_handler ext2_xattr_user_handler;
473 @@ -65,10 +67,9 @@ extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
474  extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
476  extern void ext2_xattr_delete_inode(struct inode *);
477 -extern void ext2_xattr_put_super(struct super_block *);
479 -extern int init_ext2_xattr(void);
480 -extern void exit_ext2_xattr(void);
481 +extern struct mb2_cache *ext2_xattr_create_cache(void);
482 +extern void ext2_xattr_destroy_cache(struct mb2_cache *cache);
484  extern const struct xattr_handler *ext2_xattr_handlers[];
486 @@ -93,19 +94,7 @@ ext2_xattr_delete_inode(struct inode *inode)
490 -static inline void
491 -ext2_xattr_put_super(struct super_block *sb)
495 -static inline int
496 -init_ext2_xattr(void)
498 -       return 0;
501 -static inline void
502 -exit_ext2_xattr(void)
503 +static inline void ext2_xattr_destroy_cache(struct mb2_cache *cache)
507 -- 
508 2.6.2