diff options
author | Sheng Yong <shengyong1@huawei.com> | 2016-02-19 17:14:58 +0000 |
---|---|---|
committer | luca020400 <luca.stefani.ge1@gmail.com> | 2016-04-04 17:17:55 +0200 |
commit | d9a8e137a06c0e7dc7ee94d853e8b19816754205 (patch) | |
tree | cdc0ae9b77dc7a10d60608e947c3a1d5c13f8293 | |
parent | c541f04d8bf12de46eb3c40c9ace4a904db74984 (diff) | |
download | android_external_f2fs-tools-d9a8e137a06c0e7dc7ee94d853e8b19816754205.tar.gz android_external_f2fs-tools-d9a8e137a06c0e7dc7ee94d853e8b19816754205.tar.bz2 android_external_f2fs-tools-d9a8e137a06c0e7dc7ee94d853e8b19816754205.zip |
fsck.f2fs: remove corrupted nid entry from indirect/double-indirect node
For indirect/double-indirect node, if the blk_addr in its nat entry is
corrupted, fsck could figure this out and nullify the nat entry. However,
the indirect/double-indirect node still keeps the corrupted nid. As a
result, fsck reports valid blkaddr but fixes nothing each time during
scanning all nodes, like:
=============================
[ASSERT] (sanity_check_nid: 356) --> blkaddres is not valid. [0x0]
delete in.nid[i] = 0;
[ASSERT] (sanity_check_nid: 356) --> blkaddres is not valid. [0x0]
delete in.nid[i] = 0;
[FSCK] Unreachable nat entries [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking [Ok..]
[FSCK] Hard link checking for regular file [Ok..] [0x0]
[FSCK] valid_block_count matching with CP [Ok..] [0xa51b]
[FSCK] valid_node_count matcing with CP (de lookup) [Ok..] [0x98]
[FSCK] valid_node_count matcing with CP (nat lookup) [Ok..] [0x98]
[FSCK] valid_inode_count matched with CP [Ok..] [0x7b]
[FSCK] free segment_count matched with CP [Ok..] [0x1a]
[FSCK] next block offset is free [Ok..]
[FSCK] fixing SIT types
[FSCK] other corrupted bugs [Fail]
=============================
So let's clean it.
Reported-by: Chen Yinchao <chengyinchao@huawei.com>
Signed-off-by: Liu Xue <liuxueliu.liu@huawei.com>
Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fsck/fsck.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/fsck/fsck.c b/fsck/fsck.c index 6451595..ca8ea15 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -834,7 +834,7 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, enum FILE_TYPE ftype, struct f2fs_node *node_blk, u32 *blk_cnt, struct child_info *child, struct extent_info *i_ext) { - int ret; + int need_fix = 0, ret; int i = 0; for (i = 0 ; i < NIDS_PER_BLOCK; i++) { @@ -846,9 +846,26 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, i_ext); if (!ret) *blk_cnt = *blk_cnt + 1; - else if (ret == -EINVAL) - printf("delete in.nid[i] = 0;\n"); + else if (ret == -EINVAL) { + if (!config.fix_on) + printf("should delete in.nid[i] = 0;\n"); + else { + node_blk->in.nid[i] = 0; + need_fix = 1; + FIX_MSG("Set indirect node 0x%x -> 0\n", i); + } + } + } + + if (need_fix && !config.ro) { + struct node_info ni; + nid_t nid = le32_to_cpu(node_blk->footer.nid); + + get_node_info(sbi, nid, &ni); + ret = dev_write_block(node_blk, ni.blk_addr); + ASSERT(ret >= 0); } + return 0; } @@ -857,7 +874,7 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, struct child_info *child, struct extent_info *i_ext) { int i = 0; - int ret = 0; + int need_fix = 0, ret = 0; for (i = 0; i < NIDS_PER_BLOCK; i++) { if (le32_to_cpu(node_blk->in.nid[i]) == 0x0) @@ -868,9 +885,26 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, i_ext); if (!ret) *blk_cnt = *blk_cnt + 1; - else if (ret == -EINVAL) - printf("delete in.nid[i] = 0;\n"); + else if (ret == -EINVAL) { + if (!config.fix_on) + printf("should delete in.nid[i] = 0;\n"); + else { + node_blk->in.nid[i] = 0; + need_fix = 1; + FIX_MSG("Set double indirect node 0x%x -> 0\n", i); + } + } } + + if (need_fix && !config.ro) { + struct node_info ni; + nid_t nid = le32_to_cpu(node_blk->footer.nid); + + get_node_info(sbi, nid, &ni); + ret = dev_write_block(node_blk, ni.blk_addr); + ASSERT(ret >= 0); + } + return 0; } |