aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-11-18 20:41:54 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-12-22 20:18:01 -0500
commitc11abd1a8075e428ecf5303359513b48193b29cd (patch)
tree71201566a736bec313d4123e1891c6e06327fec3
parent971767caf632190f77a40b4011c19948232eed75 (diff)
f2fs: disable the extent cache ops on high fragmented files
The f2fs manages an extent cache to search a number of consecutive data blocks very quickly. However it conducts unnecessary cache operations if the file is highly fragmented with no valid extent cache. In such the case, we don't need to handle the extent cache, but just can disable the cache facility. Nevertheless, this patch gives one more chance to enable the extent cache. For example, 1. create a file 2. write data sequentially which produces a large valid extent cache 3. update some data, resulting in a fragmented extent 4. if the fragmented extent is too small, then drop extent cache 5. close the file 6. open the file again 7. give another chance to make a new extent cache 8. write data sequentially again which creates another big extent cache. ... Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r--fs/f2fs/data.c22
-rw-r--r--fs/f2fs/f2fs.h3
2 files changed, 21 insertions, 4 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5920639ca377..2e54522a8061 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -71,6 +71,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
71 pgoff_t start_fofs, end_fofs; 71 pgoff_t start_fofs, end_fofs;
72 block_t start_blkaddr; 72 block_t start_blkaddr;
73 73
74 if (is_inode_flag_set(fi, FI_NO_EXTENT))
75 return 0;
76
74 read_lock(&fi->ext.ext_lock); 77 read_lock(&fi->ext.ext_lock);
75 if (fi->ext.len == 0) { 78 if (fi->ext.len == 0) {
76 read_unlock(&fi->ext.ext_lock); 79 read_unlock(&fi->ext.ext_lock);
@@ -109,6 +112,7 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
109 struct f2fs_inode_info *fi = F2FS_I(dn->inode); 112 struct f2fs_inode_info *fi = F2FS_I(dn->inode);
110 pgoff_t fofs, start_fofs, end_fofs; 113 pgoff_t fofs, start_fofs, end_fofs;
111 block_t start_blkaddr, end_blkaddr; 114 block_t start_blkaddr, end_blkaddr;
115 int need_update = true;
112 116
113 f2fs_bug_on(blk_addr == NEW_ADDR); 117 f2fs_bug_on(blk_addr == NEW_ADDR);
114 fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + 118 fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
@@ -117,6 +121,9 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
117 /* Update the page address in the parent node */ 121 /* Update the page address in the parent node */
118 __set_data_blkaddr(dn, blk_addr); 122 __set_data_blkaddr(dn, blk_addr);
119 123
124 if (is_inode_flag_set(fi, FI_NO_EXTENT))
125 return;
126
120 write_lock(&fi->ext.ext_lock); 127 write_lock(&fi->ext.ext_lock);
121 128
122 start_fofs = fi->ext.fofs; 129 start_fofs = fi->ext.fofs;
@@ -163,14 +170,21 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
163 fofs - start_fofs + 1; 170 fofs - start_fofs + 1;
164 fi->ext.len -= fofs - start_fofs + 1; 171 fi->ext.len -= fofs - start_fofs + 1;
165 } 172 }
166 goto end_update; 173 } else {
174 need_update = false;
167 } 175 }
168 write_unlock(&fi->ext.ext_lock);
169 return;
170 176
177 /* Finally, if the extent is very fragmented, let's drop the cache. */
178 if (fi->ext.len < F2FS_MIN_EXTENT_LEN) {
179 fi->ext.len = 0;
180 set_inode_flag(fi, FI_NO_EXTENT);
181 need_update = true;
182 }
171end_update: 183end_update:
172 write_unlock(&fi->ext.ext_lock); 184 write_unlock(&fi->ext.ext_lock);
173 sync_inode_page(dn); 185 if (need_update)
186 sync_inode_page(dn);
187 return;
174} 188}
175 189
176struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) 190struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c2de54919725..e9038bbeee9f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -169,6 +169,8 @@ enum {
169#define F2FS_LINK_MAX 32000 /* maximum link count per file */ 169#define F2FS_LINK_MAX 32000 /* maximum link count per file */
170 170
171/* for in-memory extent cache entry */ 171/* for in-memory extent cache entry */
172#define F2FS_MIN_EXTENT_LEN 16 /* minimum extent length */
173
172struct extent_info { 174struct extent_info {
173 rwlock_t ext_lock; /* rwlock for consistency */ 175 rwlock_t ext_lock; /* rwlock for consistency */
174 unsigned int fofs; /* start offset in a file */ 176 unsigned int fofs; /* start offset in a file */
@@ -889,6 +891,7 @@ enum {
889 FI_NO_ALLOC, /* should not allocate any blocks */ 891 FI_NO_ALLOC, /* should not allocate any blocks */
890 FI_UPDATE_DIR, /* should update inode block for consistency */ 892 FI_UPDATE_DIR, /* should update inode block for consistency */
891 FI_DELAY_IPUT, /* used for the recovery */ 893 FI_DELAY_IPUT, /* used for the recovery */
894 FI_NO_EXTENT, /* not to use the extent cache */
892 FI_INLINE_XATTR, /* used for inline xattr */ 895 FI_INLINE_XATTR, /* used for inline xattr */
893}; 896};
894 897