aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2015-07-01 18:19:53 -0700
committerDan Pasanen <dan.pasanen@gmail.com>2015-11-12 09:37:24 -0600
commit8913b3f0328686adb52ae3d94cefa2a6c48c2466 (patch)
treebc785df463caada209f9204b324bf5443eb139bf
parent7f5b1490a61bd75901ea242a311852729340e3f9 (diff)
downloadandroid_external_f2fs-tools-8913b3f0328686adb52ae3d94cefa2a6c48c2466.tar.gz
android_external_f2fs-tools-8913b3f0328686adb52ae3d94cefa2a6c48c2466.tar.bz2
android_external_f2fs-tools-8913b3f0328686adb52ae3d94cefa2a6c48c2466.zip
fsck.f2fs: select to update the latest valid summary
If two dnode blocks indicate one block address, it needs to keep the latest valid address selectively. Change-Id: I82574293da9999994da7a3b3fb63798f33dfb8ef Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fsck/fsck.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/fsck/fsck.c b/fsck/fsck.c
index b15edbe..bbd4cab 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -191,6 +191,47 @@ out:
return ret;
}
+static int is_valid_summary(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+ u32 blk_addr)
+{
+ u16 ofs_in_node = le16_to_cpu(sum->ofs_in_node);
+ u32 nid = le32_to_cpu(sum->nid);
+ struct f2fs_node *node_blk = NULL;
+ __le32 target_blk_addr;
+ struct node_info ni;
+ int ret = 0;
+
+ node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+ ASSERT(node_blk != NULL);
+
+ if (!IS_VALID_NID(sbi, nid))
+ goto out;
+
+ get_node_info(sbi, nid, &ni);
+
+ if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr))
+ goto out;
+
+ /* read node_block */
+ ret = dev_read_block(node_blk, ni.blk_addr);
+ ASSERT(ret >= 0);
+
+ if (le32_to_cpu(node_blk->footer.nid) != nid)
+ goto out;
+
+ /* check its block address */
+ if (node_blk->footer.nid == node_blk->footer.ino)
+ target_blk_addr = node_blk->i.i_addr[ofs_in_node];
+ else
+ target_blk_addr = node_blk->dn.addr[ofs_in_node];
+
+ if (blk_addr == le32_to_cpu(target_blk_addr))
+ ret = 1;
+out:
+ free(node_blk);
+ return ret;
+}
+
static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
u32 parent_nid, u16 idx_in_node, u8 version)
{
@@ -238,6 +279,9 @@ static int is_valid_ssa_data_blk(struct f2fs_sb_info *sbi, u32 blk_addr,
DBG(0, "Target data block addr [0x%x]\n", blk_addr);
ASSERT_MSG("Invalid data seg summary\n");
ret = -EINVAL;
+ } else if (is_valid_summary(sbi, sum_entry, blk_addr)) {
+ /* delete wrong index */
+ ret = -EINVAL;
} else {
FIX_MSG("Set data summary 0x%x -> [0x%x] [0x%x] [0x%x]",
segno, parent_nid, version, idx_in_node);