aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/file.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-14 08:52:35 +0900
committerAndreas Blaesius <skate4life@gmx.de>2016-06-05 21:20:29 +0200
commita50c5f9cb496bdfe1e6bda85584a368e50a6da2c (patch)
treef2d89c6f1edb11dd7288ca780a859ec09c02fc98 /fs/f2fs/file.c
parent34eaf6bec420bd64a9241c5954e18d0ce8fb69e1 (diff)
downloadkernel_samsung_espresso10-a50c5f9cb496bdfe1e6bda85584a368e50a6da2c.zip
kernel_samsung_espresso10-a50c5f9cb496bdfe1e6bda85584a368e50a6da2c.tar.gz
kernel_samsung_espresso10-a50c5f9cb496bdfe1e6bda85584a368e50a6da2c.tar.bz2
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> Conflicts: fs/f2fs/file.c Change-Id: Ieef8a90c123fb07290df440e9aef091f256e61c7
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 aae5d6a..4b54bc7 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -104,6 +104,24 @@ static const struct vm_operations_struct f2fs_file_vm_ops = {
.page_mkwrite = f2fs_vm_page_mkwrite,
};
+static int get_parent_ino(struct inode *inode, nid_t *pino)
+{
+ struct dentry *dentry;
+
+ inode = igrab(inode);
+ dentry = d_find_any_alias(inode);
+ iput(inode);
+ if (!dentry)
+ return 0;
+
+ inode = igrab(dentry->d_parent->d_inode);
+ dput(dentry);
+
+ *pino = inode->i_ino;
+ iput(inode);
+ return 1;
+}
+
int f2fs_sync_file(struct file *file, int datasync)
{
struct inode *inode = file->f_mapping->host;
@@ -131,7 +149,7 @@ int f2fs_sync_file(struct file *file, int datasync)
if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
need_cp = true;
- else if (is_cp_file(inode))
+ else if (file_wrong_pino(inode))
need_cp = true;
else if (!space_for_roll_forward(sbi))
need_cp = true;
@@ -139,8 +157,19 @@ int f2fs_sync_file(struct file *file, int datasync)
need_cp = true;
if (need_cp) {
+ nid_t pino;
+
/* all the dirty node pages should be flushed for POR */
ret = f2fs_sync_fs(inode->i_sb, 1);
+ if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
+ get_parent_ino(inode, &pino)) {
+ F2FS_I(inode)->i_pino = pino;
+ file_got_pino(inode);
+ mark_inode_dirty_sync(inode);
+ ret = f2fs_write_inode(inode, NULL);
+ if (ret)
+ goto out;
+ }
} else {
/* if there is no written node page, write its inode page */
while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {