summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/data.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-07 15:08:23 +0200
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-12 01:18:35 +0200
commit699489bbbea4fc3b9b735d69941cf4fca91ce1d5 (patch)
tree4b3d474252dfc93f0f4b55145d6d7193d0cbcd13 /fs/f2fs/data.c
parentf2fs: fix i_blocks translation on various types of files (diff)
downloadlinux-699489bbbea4fc3b9b735d69941cf4fca91ce1d5.tar.xz
linux-699489bbbea4fc3b9b735d69941cf4fca91ce1d5.zip
f2fs: sync dir->i_size with its block allocation
If new dentry block is allocated and its i_size is updated, we should update its inode block together in order to sync i_size and its block allocation. Otherwise, we can loose additional dentry block due to the unconsistent i_size. Errorneous Scenario ------------------- In the recovery routine, - recovery_dentry | - __f2fs_add_link | | - get_new_data_page | | | - i_size_write(new_i_size) | | | - mark_inode_dirty_sync(dir) | | - update_parent_metadata | | | - mark_inode_dirty(dir) | - write_checkpoint - sync_dirty_dir_inodes - filemap_flush(dentry_blocks) - f2fs_write_data_page - skip to write the last dentry block due to index < i_size In the above flow, new_i_size is not updated to its inode block so that the last dentry block will be lost accordingly. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r--fs/f2fs/data.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 93917e31dbdf..5b145fcc2864 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -339,6 +339,8 @@ repeat:
if (new_i_size &&
i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT));
+ /* Only the directory inode sets new_i_size */
+ set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR);
mark_inode_dirty_sync(inode);
}
return page;