提交 1dcc336b 编写于 作者: C Chao Yu 提交者: Jaegeuk Kim

f2fs: enable rb-tree extent cache

This patch enables rb-tree based extent cache in f2fs.

When we mount with "-o extent_cache", f2fs will try to add recently accessed
page-block mappings into rb-tree based extent cache as much as possible, instead
of original one extent info cache.

By this way, f2fs can support more effective cache between dnode page cache and
disk. It will supply high hit ratio in the cache with fewer memory when dnode
page cache are reclaimed in environment of low memory.

Storage: Sandisk sd card 64g
1.append write file (offset: 0, size: 128M);
2.override write file (offset: 2M, size: 1M);
3.override write file (offset: 4M, size: 1M);
...
4.override write file (offset: 48M, size: 1M);
...
5.override write file (offset: 112M, size: 1M);
6.sync
7.echo 3 > /proc/sys/vm/drop_caches
8.read file (size:128M, unit: 4k, count: 32768)
(time dd if=/mnt/f2fs/128m bs=4k count=32768)

Extent Hit Ratio:
		before		patched
Hit Ratio	121 / 1071	1071 / 1071

Performance:
		before		patched
real    	0m37.051s	0m35.556s
user    	0m0.040s	0m0.026s
sys     	0m2.990s	0m2.251s

Memory Cost:
		before		patched
Tree Count:	0		1 (size: 24 bytes)
Node Count:	0		45 (size: 1440 bytes)

v3:
 o retest and given more details of test result.
Signed-off-by: NChao Yu <chao2.yu@samsung.com>
Signed-off-by: NJaegeuk Kim <jaegeuk@kernel.org>
上级 89672159
...@@ -666,6 +666,9 @@ void f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) ...@@ -666,6 +666,9 @@ void f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
void **slot; void **slot;
unsigned int found; unsigned int found;
if (!test_opt(sbi, EXTENT_CACHE))
return;
if (available_free_memory(sbi, EXTENT_CACHE)) if (available_free_memory(sbi, EXTENT_CACHE))
return; return;
...@@ -714,6 +717,9 @@ void f2fs_destroy_extent_tree(struct inode *inode) ...@@ -714,6 +717,9 @@ void f2fs_destroy_extent_tree(struct inode *inode)
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct extent_tree *et; struct extent_tree *et;
if (!test_opt(sbi, EXTENT_CACHE))
return;
down_read(&sbi->extent_tree_lock); down_read(&sbi->extent_tree_lock);
et = radix_tree_lookup(&sbi->extent_tree_root, inode->i_ino); et = radix_tree_lookup(&sbi->extent_tree_root, inode->i_ino);
if (!et) { if (!et) {
...@@ -749,6 +755,9 @@ void f2fs_destroy_extent_tree(struct inode *inode) ...@@ -749,6 +755,9 @@ void f2fs_destroy_extent_tree(struct inode *inode)
static bool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs, static bool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs,
struct extent_info *ei) struct extent_info *ei)
{ {
if (test_opt(F2FS_I_SB(inode), EXTENT_CACHE))
return f2fs_lookup_extent_tree(inode, pgofs, ei);
return lookup_extent_info(inode, pgofs, ei); return lookup_extent_info(inode, pgofs, ei);
} }
...@@ -765,6 +774,10 @@ void f2fs_update_extent_cache(struct dnode_of_data *dn) ...@@ -765,6 +774,10 @@ void f2fs_update_extent_cache(struct dnode_of_data *dn)
fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
dn->ofs_in_node; dn->ofs_in_node;
if (test_opt(F2FS_I_SB(dn->inode), EXTENT_CACHE))
return f2fs_update_extent_tree(dn->inode, fofs,
dn->data_blkaddr);
if (update_extent_info(dn->inode, fofs, dn->data_blkaddr)) if (update_extent_info(dn->inode, fofs, dn->data_blkaddr))
sync_inode_page(dn); sync_inode_page(dn);
} }
......
...@@ -335,6 +335,7 @@ void f2fs_evict_inode(struct inode *inode) ...@@ -335,6 +335,7 @@ void f2fs_evict_inode(struct inode *inode)
no_delete: no_delete:
stat_dec_inline_dir(inode); stat_dec_inline_dir(inode);
stat_dec_inline_inode(inode); stat_dec_inline_inode(inode);
f2fs_destroy_extent_tree(inode);
invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino);
if (xnid) if (xnid)
invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid); invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
......
...@@ -277,6 +277,9 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi) ...@@ -277,6 +277,9 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi)
void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
{ {
/* try to shrink extent cache when there is no enough memory */
f2fs_shrink_extent_tree(sbi, EXTENT_CACHE_SHRINK_NUMBER);
/* check the # of cached NAT entries and prefree segments */ /* check the # of cached NAT entries and prefree segments */
if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) || if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) ||
excess_prefree_segs(sbi) || excess_prefree_segs(sbi) ||
......
...@@ -1079,6 +1079,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1079,6 +1079,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
INIT_LIST_HEAD(&sbi->dir_inode_list); INIT_LIST_HEAD(&sbi->dir_inode_list);
spin_lock_init(&sbi->dir_inode_lock); spin_lock_init(&sbi->dir_inode_lock);
init_extent_cache_info(sbi);
init_ino_entry_info(sbi); init_ino_entry_info(sbi);
/* setup f2fs internal modules */ /* setup f2fs internal modules */
...@@ -1285,10 +1287,13 @@ static int __init init_f2fs_fs(void) ...@@ -1285,10 +1287,13 @@ static int __init init_f2fs_fs(void)
err = create_checkpoint_caches(); err = create_checkpoint_caches();
if (err) if (err)
goto free_segment_manager_caches; goto free_segment_manager_caches;
err = create_extent_cache();
if (err)
goto free_checkpoint_caches;
f2fs_kset = kset_create_and_add("f2fs", NULL, fs_kobj); f2fs_kset = kset_create_and_add("f2fs", NULL, fs_kobj);
if (!f2fs_kset) { if (!f2fs_kset) {
err = -ENOMEM; err = -ENOMEM;
goto free_checkpoint_caches; goto free_extent_cache;
} }
err = register_filesystem(&f2fs_fs_type); err = register_filesystem(&f2fs_fs_type);
if (err) if (err)
...@@ -1299,6 +1304,8 @@ static int __init init_f2fs_fs(void) ...@@ -1299,6 +1304,8 @@ static int __init init_f2fs_fs(void)
free_kset: free_kset:
kset_unregister(f2fs_kset); kset_unregister(f2fs_kset);
free_extent_cache:
destroy_extent_cache();
free_checkpoint_caches: free_checkpoint_caches:
destroy_checkpoint_caches(); destroy_checkpoint_caches();
free_segment_manager_caches: free_segment_manager_caches:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册