diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-02-03 03:24:51 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-02-17 00:58:52 -0500 |
commit | 924a2ddbd0c2829ebca9ac899522cbb16a9b6d8c (patch) | |
tree | 794457d4b817008f58a274231a4d6418e66923b0 | |
parent | 1b1f559fc362f96869b7e04ef9825b1039b9a67d (diff) |
f2fs: fix the potential mismatch between dir's i_size and i_blocks
This is the erroneous scenario.
i_size on-disk i_size i_blocks
__f2fs_add_link() 4096 4096 2
get_new_data_page 8192 4096 3
-ENOSPC = init_inode_metadata
checkpoint - 4096 3
POR and reboot
__f2fs_add_link() 4096 4096 3
page = get_new_data_page (page->index = 1 by NEW_ADDR)
add a dentry to the page successfully
f2fs_rmdir()
f2fs_empty_dir() 4096 4096 3
f2fs_unlink() goes, since there is no valid dentry due to i_size = 4096.
But, still there is one dentry in page->index = 1.
So this patch moves the code to write dir->i_size into on-disk i_size in order
to sync dir's i_size, on-disk i_size, and its i_blocks.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r-- | fs/f2fs/dir.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 2b7c255bcbdf..bfcb4ae241f8 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -395,9 +395,6 @@ static void update_parent_metadata(struct inode *dir, struct inode *inode, | |||
395 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | 395 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
396 | } | 396 | } |
397 | 397 | ||
398 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) | ||
399 | update_inode_page(dir); | ||
400 | |||
401 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) | 398 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) |
402 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); | 399 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); |
403 | } | 400 | } |
@@ -511,7 +508,10 @@ add_dentry: | |||
511 | 508 | ||
512 | update_parent_metadata(dir, inode, current_depth); | 509 | update_parent_metadata(dir, inode, current_depth); |
513 | fail: | 510 | fail: |
514 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | 511 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) { |
512 | update_inode_page(dir); | ||
513 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | ||
514 | } | ||
515 | kunmap(dentry_page); | 515 | kunmap(dentry_page); |
516 | f2fs_put_page(dentry_page, 1); | 516 | f2fs_put_page(dentry_page, 1); |
517 | return err; | 517 | return err; |