diff options
author | Chao Yu <chao2.yu@samsung.com> | 2015-03-19 07:27:51 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-04-10 18:08:51 -0400 |
commit | 0bdee482509fe8c3cf0e66231ed37b8e70954093 (patch) | |
tree | 2477ba4cbcefcbf2fce8e860e1d7e70c6aafa524 | |
parent | 028a41e89383e1208dff1afe3e260b8cb6d3431c (diff) |
f2fs: preserve extent info for extent cache
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>
-rw-r--r-- | fs/f2fs/data.c | 49 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 8 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 5 |
3 files changed, 62 insertions, 0 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e3be4be3a6d8..8a940e518be8 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -719,6 +719,55 @@ update_extent: | |||
719 | atomic_dec(&et->refcount); | 719 | atomic_dec(&et->refcount); |
720 | } | 720 | } |
721 | 721 | ||
722 | void f2fs_preserve_extent_tree(struct inode *inode) | ||
723 | { | ||
724 | struct extent_tree *et; | ||
725 | struct extent_info *ext = &F2FS_I(inode)->ext; | ||
726 | bool sync = false; | ||
727 | |||
728 | if (!test_opt(F2FS_I_SB(inode), EXTENT_CACHE)) | ||
729 | return; | ||
730 | |||
731 | et = __find_extent_tree(F2FS_I_SB(inode), inode->i_ino); | ||
732 | if (!et) { | ||
733 | if (ext->len) { | ||
734 | ext->len = 0; | ||
735 | update_inode_page(inode); | ||
736 | } | ||
737 | return; | ||
738 | } | ||
739 | |||
740 | read_lock(&et->lock); | ||
741 | if (et->count) { | ||
742 | struct extent_node *en; | ||
743 | |||
744 | if (et->cached_en) { | ||
745 | en = et->cached_en; | ||
746 | } else { | ||
747 | struct rb_node *node = rb_first(&et->root); | ||
748 | |||
749 | if (!node) | ||
750 | node = rb_last(&et->root); | ||
751 | en = rb_entry(node, struct extent_node, rb_node); | ||
752 | } | ||
753 | |||
754 | if (__is_extent_same(ext, &en->ei)) | ||
755 | goto out; | ||
756 | |||
757 | *ext = en->ei; | ||
758 | sync = true; | ||
759 | } else if (ext->len) { | ||
760 | ext->len = 0; | ||
761 | sync = true; | ||
762 | } | ||
763 | out: | ||
764 | read_unlock(&et->lock); | ||
765 | atomic_dec(&et->refcount); | ||
766 | |||
767 | if (sync) | ||
768 | update_inode_page(inode); | ||
769 | } | ||
770 | |||
722 | void f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | 771 | void f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) |
723 | { | 772 | { |
724 | struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; | 773 | struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 431b4af693e5..0be198339c3b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -371,6 +371,13 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs, | |||
371 | ei->len = len; | 371 | ei->len = len; |
372 | } | 372 | } |
373 | 373 | ||
374 | static inline bool __is_extent_same(struct extent_info *ei1, | ||
375 | struct extent_info *ei2) | ||
376 | { | ||
377 | return (ei1->fofs == ei2->fofs && ei1->blk == ei2->blk && | ||
378 | ei1->len == ei2->len); | ||
379 | } | ||
380 | |||
374 | static inline bool __is_extent_mergeable(struct extent_info *back, | 381 | static inline bool __is_extent_mergeable(struct extent_info *back, |
375 | struct extent_info *front) | 382 | struct extent_info *front) |
376 | { | 383 | { |
@@ -1598,6 +1605,7 @@ void f2fs_shrink_extent_tree(struct f2fs_sb_info *, int); | |||
1598 | void f2fs_destroy_extent_tree(struct inode *); | 1605 | void f2fs_destroy_extent_tree(struct inode *); |
1599 | void f2fs_init_extent_cache(struct inode *, struct f2fs_extent *); | 1606 | void f2fs_init_extent_cache(struct inode *, struct f2fs_extent *); |
1600 | void f2fs_update_extent_cache(struct dnode_of_data *); | 1607 | void f2fs_update_extent_cache(struct dnode_of_data *); |
1608 | void f2fs_preserve_extent_tree(struct inode *); | ||
1601 | struct page *find_data_page(struct inode *, pgoff_t, bool); | 1609 | struct page *find_data_page(struct inode *, pgoff_t, bool); |
1602 | struct page *get_lock_data_page(struct inode *, pgoff_t); | 1610 | struct page *get_lock_data_page(struct inode *, pgoff_t); |
1603 | struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); | 1611 | struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9e64d3efb2d2..07237ac2935e 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -343,7 +343,12 @@ void f2fs_evict_inode(struct inode *inode) | |||
343 | no_delete: | 343 | no_delete: |
344 | stat_dec_inline_dir(inode); | 344 | stat_dec_inline_dir(inode); |
345 | stat_dec_inline_inode(inode); | 345 | stat_dec_inline_inode(inode); |
346 | |||
347 | /* update extent info in inode */ | ||
348 | if (inode->i_nlink) | ||
349 | f2fs_preserve_extent_tree(inode); | ||
346 | f2fs_destroy_extent_tree(inode); | 350 | f2fs_destroy_extent_tree(inode); |
351 | |||
347 | invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); | 352 | invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); |
348 | if (xnid) | 353 | if (xnid) |
349 | invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); | 354 | invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); |