diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-08-29 11:46:25 -0700 |
---|---|---|
committer | JP Abgrall <jpa@google.com> | 2014-09-08 14:55:01 -0700 |
commit | dc530859c5e422b10ab70bc3b9d4b7ff0d004d57 (patch) | |
tree | 6ef0f9a5c24f554a1da48d56dc52a30492512da1 | |
parent | fffeed796a79fa6621d01b0e4c5fa18d9d89cdd7 (diff) | |
download | android_external_f2fs-tools-dc530859c5e422b10ab70bc3b9d4b7ff0d004d57.tar.gz android_external_f2fs-tools-dc530859c5e422b10ab70bc3b9d4b7ff0d004d57.tar.bz2 android_external_f2fs-tools-dc530859c5e422b10ab70bc3b9d4b7ff0d004d57.zip |
fsck.f2fs: fix inode block inconsistency
This patch is to fix inode block inconsistency such as iblocks and ilinks.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fsck/fsck.c | 61 | ||||
-rw-r--r-- | include/f2fs_fs.h | 1 | ||||
-rw-r--r-- | lib/libf2fs_io.c | 5 |
3 files changed, 43 insertions, 24 deletions
diff --git a/fsck/fsck.c b/fsck/fsck.c index 49d9ccc..17cf29b 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -319,6 +319,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, u32 i_links = le32_to_cpu(node_blk->i.i_links); u64 i_blocks = le64_to_cpu(node_blk->i.i_blocks); unsigned int idx = 0; + int need_fix = 0; int ret; if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) @@ -339,8 +340,11 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, if (find_and_dec_hard_link_list(sbi, nid)) { ASSERT_MSG("[0x%x] needs more i_links=0x%x", nid, i_links); - if (config.fix_cnt) - printf("TODO: i_links++\n"); + if (config.fix_cnt) { + node_blk->i.i_links = + cpu_to_le32(i_links + 1); + need_fix = 1; + } } /* No need to go deep into the node */ return; @@ -366,8 +370,12 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, &child_cnt, &child_files, (i_blocks == *blk_cnt), ftype, nid, idx, ni->version); - if (!ret) + if (!ret) { *blk_cnt = *blk_cnt + 1; + } else if (config.fix_cnt) { + node_blk->i.i_addr[idx] = 0; + need_fix = 1; + } } } @@ -386,10 +394,12 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, ret = fsck_chk_node_blk(sbi, &node_blk->i, le32_to_cpu(node_blk->i.i_nid[idx]), ftype, ntype, blk_cnt); - if (!ret) + if (!ret) { *blk_cnt = *blk_cnt + 1; - else if (config.fix_cnt) - printf("TODO delete i_nid[idx] = 0;\n"); + } else if (config.fix_cnt) { + node_blk->i.i_nid[idx] = 0; + need_fix = 1; + } } } check: @@ -404,28 +414,31 @@ check: le32_to_cpu(node_blk->footer.ino), node_blk->i.i_name, (u32)i_blocks); - if ((ftype == F2FS_FT_DIR && i_links != child_cnt) || - (i_blocks != *blk_cnt)) { - if (!config.fix_cnt) - print_node_info(node_blk); - - /* node_blk, ni.blkaddr, child_cnt, *blk_cnt */ - if (config.fix_cnt) - printf("TODO fix_inode_block\n"); - else - print_node_info(node_blk); - DBG(1, "blk cnt [0x%x]\n", *blk_cnt); - DBG(1, "child cnt [0x%x]\n", child_cnt); - } - if (i_blocks != *blk_cnt) + + if (i_blocks != *blk_cnt) { ASSERT_MSG("ino: 0x%x has i_blocks: %lu, but has %u blocks", - nid, i_blocks, *blk_cnt); - if (ftype == F2FS_FT_DIR && i_links != child_cnt) + nid, i_blocks, *blk_cnt); + if (config.fix_cnt) { + node_blk->i.i_blocks = cpu_to_le64(*blk_cnt); + need_fix = 1; + } + } + if (ftype == F2FS_FT_DIR && i_links != child_cnt) { ASSERT_MSG("ino: 0x%x has i_links: %u but real links: %u", - nid, i_links, child_cnt); + nid, i_links, child_cnt); + if (config.fix_cnt) { + node_blk->i.i_links = cpu_to_le32(child_cnt); + need_fix = 1; + } + } + if (ftype == F2FS_FT_ORPHAN && i_links) ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u", - nid, i_links); + nid, i_links); + if (need_fix) { + ret = dev_write_block(node_blk, ni->blk_addr); + ASSERT(ret >= 0); + } } int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index c3cc2aa..3b75bff 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -676,6 +676,7 @@ extern void f2fs_finalize_device(struct f2fs_configuration *); extern int dev_read(void *, __u64, size_t); extern int dev_write(void *, __u64, size_t); +extern int dev_write_block(void *, __u64); extern int dev_write_dump(void *, __u64, size_t); /* All bytes in the buffer must be 0 use dev_fill(). */ extern int dev_fill(void *, __u64, size_t); diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c index d5ced53..0c89ee4 100644 --- a/lib/libf2fs_io.c +++ b/lib/libf2fs_io.c @@ -46,6 +46,11 @@ int dev_write(void *buf, __u64 offset, size_t len) return 0; } +int dev_write_block(void *buf, __u64 blk_addr) +{ + return dev_write(buf, blk_addr * F2FS_BLKSIZE, F2FS_BLKSIZE); +} + int dev_write_dump(void *buf, __u64 offset, size_t len) { if (lseek64(config.dump_fd, (off64_t)offset, SEEK_SET) < 0) |