This patch detects any corrupted superblock and fix misalignment when it finds, which is synced with the f2fs kernel module.
Signed-off-by: Jaegeuk Kim <[email protected]> --- fsck/mount.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/fsck/mount.c b/fsck/mount.c index 37a0025..67c681e 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -265,7 +265,90 @@ void print_sb_state(struct f2fs_super_block *sb) MSG(0, "\n"); } -int sanity_check_raw_super(struct f2fs_super_block *sb) +static inline int sanity_check_area_boundary(struct f2fs_super_block *sb, + u64 offset) +{ + u32 segment0_blkaddr = get_sb(segment0_blkaddr); + u32 cp_blkaddr = get_sb(cp_blkaddr); + u32 sit_blkaddr = get_sb(sit_blkaddr); + u32 nat_blkaddr = get_sb(nat_blkaddr); + u32 ssa_blkaddr = get_sb(ssa_blkaddr); + u32 main_blkaddr = get_sb(main_blkaddr); + u32 segment_count_ckpt = get_sb(segment_count_ckpt); + u32 segment_count_sit = get_sb(segment_count_sit); + u32 segment_count_nat = get_sb(segment_count_nat); + u32 segment_count_ssa = get_sb(segment_count_ssa); + u32 segment_count_main = get_sb(segment_count_main); + u32 segment_count = get_sb(segment_count); + u32 log_blocks_per_seg = get_sb(log_blocks_per_seg); + u64 main_end_blkaddr = main_blkaddr + + (segment_count_main << log_blocks_per_seg); + u64 seg_end_blkaddr = segment0_blkaddr + + (segment_count << log_blocks_per_seg); + + if (segment0_blkaddr != cp_blkaddr) { + MSG(0, "\tMismatch segment0(%u) cp_blkaddr(%u)\n", + segment0_blkaddr, cp_blkaddr); + return -1; + } + + if (cp_blkaddr + (segment_count_ckpt << log_blocks_per_seg) != + sit_blkaddr) { + MSG(0, "\tWrong CP boundary, start(%u) end(%u) blocks(%u)\n", + cp_blkaddr, sit_blkaddr, + segment_count_ckpt << log_blocks_per_seg); + return -1; + } + + if (sit_blkaddr + (segment_count_sit << log_blocks_per_seg) != + nat_blkaddr) { + MSG(0, "\tWrong SIT boundary, start(%u) end(%u) blocks(%u)\n", + sit_blkaddr, nat_blkaddr, + segment_count_sit << log_blocks_per_seg); + return -1; + } + + if (nat_blkaddr + (segment_count_nat << log_blocks_per_seg) != + ssa_blkaddr) { + MSG(0, "\tWrong NAT boundary, start(%u) end(%u) blocks(%u)\n", + nat_blkaddr, ssa_blkaddr, + segment_count_nat << log_blocks_per_seg); + return -1; + } + + if (ssa_blkaddr + (segment_count_ssa << log_blocks_per_seg) != + main_blkaddr) { + MSG(0, "\tWrong SSA boundary, start(%u) end(%u) blocks(%u)\n", + ssa_blkaddr, main_blkaddr, + segment_count_ssa << log_blocks_per_seg); + return -1; + } + + if (main_end_blkaddr > seg_end_blkaddr) { + MSG(0, "\tWrong MAIN_AREA, start(%u) end(%u) block(%u)\n", + main_blkaddr, + segment0_blkaddr + + (segment_count << log_blocks_per_seg), + segment_count_main << log_blocks_per_seg); + return -1; + } else if (main_end_blkaddr < seg_end_blkaddr) { + int err; + + set_sb(segment_count, (main_end_blkaddr - + segment0_blkaddr) >> log_blocks_per_seg); + + err = dev_write(sb, offset, sizeof(struct f2fs_super_block)); + MSG(0, "Info: Fix alignment: %s, start(%u) end(%u) block(%u)\n", + err ? "failed": "done", + main_blkaddr, + segment0_blkaddr + + (segment_count << log_blocks_per_seg), + segment_count_main << log_blocks_per_seg); + } + return 0; +} + +int sanity_check_raw_super(struct f2fs_super_block *sb, u64 offset) { unsigned int blocksize; @@ -279,6 +362,15 @@ int sanity_check_raw_super(struct f2fs_super_block *sb) if (F2FS_BLKSIZE != blocksize) return -1; + /* check log blocks per segment */ + if (get_sb(log_blocks_per_seg) != 9) + return -1; + + if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE || + get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) + return -1; + + /* Currently, support 512/1024/2048/4096 bytes sector size */ if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE || get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) return -1; @@ -287,6 +379,13 @@ int sanity_check_raw_super(struct f2fs_super_block *sb) F2FS_MAX_LOG_SECTOR_SIZE) return -1; + /* check reserved ino info */ + if (get_sb(node_ino) != 1 || get_sb(meta_ino) != 2 || + get_sb(root_ino) != 3) + return -1; + + if (sanity_check_area_boundary(sb, offset)) + return -1; return 0; } @@ -304,7 +403,7 @@ int validate_super_block(struct f2fs_sb_info *sbi, int block) if (dev_read(sbi->raw_super, offset, sizeof(struct f2fs_super_block))) return -1; - if (!sanity_check_raw_super(sbi->raw_super)) { + if (!sanity_check_raw_super(sbi->raw_super, offset)) { /* get kernel version */ if (config.kd >= 0) { dev_read_version(config.version, 0, VERSION_LEN); -- 2.6.3 ------------------------------------------------------------------------------ Transform Data into Opportunity. Accelerate data analysis in your applications with Intel Data Analytics Acceleration Library. Click to learn more. http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
