f2fs: load largest extent all the time
authorJaegeuk Kim <jaegeuk@kernel.org>
Mon, 28 Dec 2015 19:39:06 +0000 (11:39 -0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 30 Dec 2015 18:14:20 +0000 (10:14 -0800)
Otherwise, we can get mismatched largest extent information.

One example is:
1. mount f2fs w/ extent_cache
2. make a small extent
3. umount
4. mount f2fs w/o extent_cache
5. update the largest extent
6. umount
7. mount f2fs w/ extent_cache
8. get the old extent made by #2

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/extent_cache.c
fs/f2fs/f2fs.h
fs/f2fs/inode.c

index 5305a29f91a33514ca20ec2b9f00917087b21016..b37184f720e8988d54daa4962334f14caefa1ef4 100644 (file)
@@ -166,20 +166,27 @@ static void __drop_largest_extent(struct inode *inode,
                largest->len = 0;
 }
 
-void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
+/* return true, if inode page is changed */
+bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct extent_tree *et;
        struct extent_node *en;
        struct extent_info ei;
 
-       if (!f2fs_may_extent_tree(inode))
-               return;
+       if (!f2fs_may_extent_tree(inode)) {
+               /* drop largest extent */
+               if (i_ext && i_ext->len) {
+                       i_ext->len = 0;
+                       return true;
+               }
+               return false;
+       }
 
        et = __grab_extent_tree(inode);
 
-       if (!i_ext || le32_to_cpu(i_ext->len) < F2FS_MIN_EXTENT_LEN)
-               return;
+       if (!i_ext || !i_ext->len)
+               return false;
 
        set_extent_info(&ei, le32_to_cpu(i_ext->fofs),
                le32_to_cpu(i_ext->blk), le32_to_cpu(i_ext->len));
@@ -196,6 +203,7 @@ void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
        }
 out:
        write_unlock(&et->lock);
+       return false;
 }
 
 static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
index e04b2be6cd64dea554bbf1e2224af49b06bf0a0c..a3395088e0f0ee2674cff36684da65c7b07f2c16 100644 (file)
@@ -2083,7 +2083,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *);
  * extent_cache.c
  */
 unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
-void f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
+bool f2fs_init_extent_tree(struct inode *, struct f2fs_extent *);
 unsigned int f2fs_destroy_extent_node(struct inode *);
 void f2fs_destroy_extent_tree(struct inode *);
 bool f2fs_lookup_extent_cache(struct inode *, pgoff_t, struct extent_info *);
index ec3fb32c472622dfb9085b15491dba34546be655..e95500802daa64d7fe2f56000dd9f0f7f6386393 100644 (file)
@@ -138,7 +138,8 @@ static int do_read_inode(struct inode *inode)
        fi->i_pino = le32_to_cpu(ri->i_pino);
        fi->i_dir_level = ri->i_dir_level;
 
-       f2fs_init_extent_tree(inode, &ri->i_ext);
+       if (f2fs_init_extent_tree(inode, &ri->i_ext))
+               set_page_dirty(node_page);
 
        get_inline_info(fi, ri);