diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-06-14 08:52:35 +0900 |
---|---|---|
committer | Andreas Blaesius <skate4life@gmx.de> | 2016-06-05 21:20:29 +0200 |
commit | a50c5f9cb496bdfe1e6bda85584a368e50a6da2c (patch) | |
tree | f2d89c6f1edb11dd7288ca780a859ec09c02fc98 /fs/f2fs/file.c | |
parent | 34eaf6bec420bd64a9241c5954e18d0ce8fb69e1 (diff) | |
download | kernel_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.c | 31 |
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)) { |