aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/file.c
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 /fs/f2fs/file.c
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>
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r--fs/f2fs/file.c31
1 files changed, 30 insertions, 1 deletions
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)) {