aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yong <shengyong1@huawei.com>2016-02-19 17:14:58 +0000
committerluca020400 <luca.stefani.ge1@gmail.com>2016-04-04 17:17:55 +0200
commitd9a8e137a06c0e7dc7ee94d853e8b19816754205 (patch)
treecdc0ae9b77dc7a10d60608e947c3a1d5c13f8293
parentc541f04d8bf12de46eb3c40c9ace4a904db74984 (diff)
downloadandroid_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.c46
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;
}