aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-13 19:52:35 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-13 20:04:45 -0400
commit354a3399dc6f7e556d04e1c731cd50e08eeb44bd (patch)
tree755e9c85c22dd0aa8dfdfc204e5697afd99b67af
parentb25958b6ecf1dce087e62b9aa27cf8f2fe9b5c86 (diff)
f2fs: recover wrong pino after checkpoint during fsync
If a file is linked, f2fs loose its parent inode number so that fsync calls for the linked file should do checkpoint all the time. But, if we can recover its parent inode number after the checkpoint, we can adjust roll-forward mechanism for the further fsync calls, which is able to improve the fsync performance significatly. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r--fs/f2fs/dir.c2
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/file.c31
-rw-r--r--fs/f2fs/namei.c2
-rw-r--r--fs/f2fs/node.h15
-rw-r--r--fs/f2fs/segment.c2
6 files changed, 45 insertions, 9 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 69ca049b5168..4f21452f929d 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -356,7 +356,7 @@ static struct page *init_inode_metadata(struct inode *inode,
356 * We lost i_pino from now on. 356 * We lost i_pino from now on.
357 */ 357 */
358 if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { 358 if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
359 set_cp_file(inode); 359 file_lost_pino(inode);
360 inc_nlink(inode); 360 inc_nlink(inode);
361 } 361 }
362 return page; 362 return page;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 3e7cb33b64d3..863a5e91d84a 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -151,7 +151,7 @@ struct extent_info {
151 * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. 151 * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
152 */ 152 */
153#define FADVISE_COLD_BIT 0x01 153#define FADVISE_COLD_BIT 0x01
154#define FADVISE_CP_BIT 0x02 154#define FADVISE_LOST_PINO_BIT 0x02
155 155
156struct f2fs_inode_info { 156struct f2fs_inode_info {
157 struct inode vfs_inode; /* serve a vfs inode */ 157 struct inode vfs_inode; /* serve a vfs inode */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index fda226ff1849..d2d2b7dbdcc1 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -102,6 +102,24 @@ static const struct vm_operations_struct f2fs_file_vm_ops = {
102 .remap_pages = generic_file_remap_pages, 102 .remap_pages = generic_file_remap_pages,
103}; 103};
104 104
105static int get_parent_ino(struct inode *inode, nid_t *pino)
106{
107 struct dentry *dentry;
108
109 inode = igrab(inode);
110 dentry = d_find_any_alias(inode);
111 iput(inode);
112 if (!dentry)
113 return 0;
114
115 inode = igrab(dentry->d_parent->d_inode);
116 dput(dentry);
117
118 *pino = inode->i_ino;
119 iput(inode);
120 return 1;
121}
122
105int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) 123int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
106{ 124{
107 struct inode *inode = file->f_mapping->host; 125 struct inode *inode = file->f_mapping->host;
@@ -134,7 +152,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
134 152
135 if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) 153 if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
136 need_cp = true; 154 need_cp = true;
137 else if (is_cp_file(inode)) 155 else if (file_wrong_pino(inode))
138 need_cp = true; 156 need_cp = true;
139 else if (!space_for_roll_forward(sbi)) 157 else if (!space_for_roll_forward(sbi))
140 need_cp = true; 158 need_cp = true;
@@ -142,8 +160,19 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
142 need_cp = true; 160 need_cp = true;
143 161
144 if (need_cp) { 162 if (need_cp) {
163 nid_t pino;
164
145 /* all the dirty node pages should be flushed for POR */ 165 /* all the dirty node pages should be flushed for POR */
146 ret = f2fs_sync_fs(inode->i_sb, 1); 166 ret = f2fs_sync_fs(inode->i_sb, 1);
167 if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
168 get_parent_ino(inode, &pino)) {
169 F2FS_I(inode)->i_pino = pino;
170 file_got_pino(inode);
171 mark_inode_dirty_sync(inode);
172 ret = f2fs_write_inode(inode, NULL);
173 if (ret)
174 goto out;
175 }
147 } else { 176 } else {
148 /* if there is no written node page, write its inode page */ 177 /* if there is no written node page, write its inode page */
149 while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { 178 while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 810444ee6b5e..64c07169df05 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -112,7 +112,7 @@ static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode,
112 int count = le32_to_cpu(sbi->raw_super->extension_count); 112 int count = le32_to_cpu(sbi->raw_super->extension_count);
113 for (i = 0; i < count; i++) { 113 for (i = 0; i < count; i++) {
114 if (is_multimedia_file(name, extlist[i])) { 114 if (is_multimedia_file(name, extlist[i])) {
115 set_cold_file(inode); 115 file_set_cold(inode);
116 break; 116 break;
117 } 117 }
118 } 118 }
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index a503661307db..c65fb4f4230f 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -285,10 +285,17 @@ static inline void set_file(struct inode *inode, int type)
285 F2FS_I(inode)->i_advise |= type; 285 F2FS_I(inode)->i_advise |= type;
286} 286}
287 287
288#define is_cold_file(inode) is_file(inode, FADVISE_COLD_BIT) 288static inline void clear_file(struct inode *inode, int type)
289#define is_cp_file(inode) is_file(inode, FADVISE_CP_BIT) 289{
290#define set_cold_file(inode) set_file(inode, FADVISE_COLD_BIT) 290 F2FS_I(inode)->i_advise &= ~type;
291#define set_cp_file(inode) set_file(inode, FADVISE_CP_BIT) 291}
292
293#define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT)
294#define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
295#define file_set_cold(inode) set_file(inode, FADVISE_COLD_BIT)
296#define file_lost_pino(inode) set_file(inode, FADVISE_LOST_PINO_BIT)
297#define file_clear_cold(inode) clear_file(inode, FADVISE_COLD_BIT)
298#define file_got_pino(inode) clear_file(inode, FADVISE_LOST_PINO_BIT)
292 299
293static inline int is_cold_data(struct page *page) 300static inline int is_cold_data(struct page *page)
294{ 301{
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index b15debcccc23..0e1a60a4eb3f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -796,7 +796,7 @@ static int __get_segment_type_6(struct page *page, enum page_type p_type)
796 796
797 if (S_ISDIR(inode->i_mode)) 797 if (S_ISDIR(inode->i_mode))
798 return CURSEG_HOT_DATA; 798 return CURSEG_HOT_DATA;
799 else if (is_cold_data(page) || is_cold_file(inode)) 799 else if (is_cold_data(page) || file_is_cold(inode))
800 return CURSEG_COLD_DATA; 800 return CURSEG_COLD_DATA;
801 else 801 else
802 return CURSEG_WARM_DATA; 802 return CURSEG_WARM_DATA;