f2fs: preserve extent info for extent cache
authorChao Yu <chao2.yu@samsung.com>
Thu, 19 Mar 2015 11:27:51 +0000 (19:27 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 10 Apr 2015 22:08:51 +0000 (15:08 -0700)
This patch tries to preserve last extent info in extent tree cache into on-disk
inode, so this can help us to reuse the last extent info next time for
performance.

Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/inode.c

index e3be4be3a6d8c24665943bebc8ee662817cdac80..8a940e518be8dd6f390cda7fc56831106b0b80f5 100644 (file)
@@ -719,6 +719,55 @@ update_extent:
        atomic_dec(&et->refcount);
 }
 
+void f2fs_preserve_extent_tree(struct inode *inode)
+{
+       struct extent_tree *et;
+       struct extent_info *ext = &F2FS_I(inode)->ext;
+       bool sync = false;
+
+       if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE))
+               return;
+
+       et = __find_extent_tree(F2FS_I_SB(inode), inode->i_ino);
+       if (!et) {
+               if (ext->len) {
+                       ext->len = 0;
+                       update_inode_page(inode);
+               }
+               return;
+       }
+
+       read_lock(&et->lock);
+       if (et->count) {
+               struct extent_node *en;
+
+               if (et->cached_en) {
+                       en = et->cached_en;
+               } else {
+                       struct rb_node *node = rb_first(&et->root);
+
+                       if (!node)
+                               node = rb_last(&et->root);
+                       en = rb_entry(node, struct extent_node, rb_node);
+               }
+
+               if (__is_extent_same(ext, &en->ei))
+                       goto out;
+
+               *ext = en->ei;
+               sync = true;
+       } else if (ext->len) {
+               ext->len = 0;
+               sync = true;
+       }
+out:
+       read_unlock(&et->lock);
+       atomic_dec(&et->refcount);
+
+       if (sync)
+               update_inode_page(inode);
+}
+
 void f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
 {
        struct extent_tree *treevec[EXT_TREE_VEC_SIZE];
index 431b4af693e512dfc192fb545f686446f7d7b66d..0be198339c3b7360f20b727e4d043692ceb45843 100644 (file)
@@ -371,6 +371,13 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
        ei->len = len;
 }
 
+static inline bool __is_extent_same(struct extent_info *ei1,
+                                               struct extent_info *ei2)
+{
+       return (ei1->fofs == ei2->fofs && ei1->blk == ei2->blk &&
+                                               ei1->len == ei2->len);
+}
+
 static inline bool __is_extent_mergeable(struct extent_info *back,
                                                struct extent_info *front)
 {
@@ -1598,6 +1605,7 @@ void f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
 void f2fs_destroy_extent_tree(struct inode *);
 void f2fs_init_extent_cache(struct inode *, struct f2fs_extent *);
 void f2fs_update_extent_cache(struct dnode_of_data *);
+void f2fs_preserve_extent_tree(struct inode *);
 struct page *find_data_page(struct inode *, pgoff_t, bool);
 struct page *get_lock_data_page(struct inode *, pgoff_t);
 struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
index 9e64d3efb2d26a1120918d6d96cfb875e2252320..07237ac2935e87d5cd112f28d4de7588edbdf1fa 100644 (file)
@@ -343,7 +343,12 @@ void f2fs_evict_inode(struct inode *inode)
 no_delete:
        stat_dec_inline_dir(inode);
        stat_dec_inline_inode(inode);
+
+       /* update extent info in inode */
+       if (inode->i_nlink)
+               f2fs_preserve_extent_tree(inode);
        f2fs_destroy_extent_tree(inode);
+
        invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino);
        if (xnid)
                invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);