diff --git a/fsck/fsck.c b/fsck/fsck.c index 57fe423a..d1c1a2d6 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -1307,17 +1307,52 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, nid, i_links, child.links); } } - if ((child.dot == 0 || child.dotdot == 0) && - !(node_blk->i.i_inline & F2FS_INLINE_DOTS)) { - ASSERT_MSG("ino: 0x%x dot: %u, dotdot: %u", + if (child.dot == 0 || child.dotdot == 0) { + ASSERT_MSG("ino: 0x%x has no '.' and/or '..' dirents, dot: %u, dotdot: %u", nid, child.dot, child.dotdot); if (c.fix_on) { - node_blk->i.i_inline |= F2FS_INLINE_DOTS; + umode_t mode = le16_to_cpu(node_blk->i.i_mode); + block_t blkaddr; + + ret = convert_inline_dentry(sbi, node_blk, + &ni->blk_addr); + FIX_MSG("convert inline dentry ino: %u, pino: %u, ret: %d", + nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + + if (child.dot == 0) { + char *name = "."; + + ret = f2fs_add_link(sbi, node_blk, + (const unsigned char *)name, + 1, nid, map_de_type(mode), + &blkaddr, 0); + FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d", + name, nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + } + + if (child.dotdot == 0) { + char *name = ".."; + + ret = f2fs_add_link(sbi, node_blk, + (const unsigned char *)name, + 2, child_d->p_ino, + map_de_type(mode), + &blkaddr, 0); + FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d", + name, nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + } + need_fix = 1; - FIX_MSG("Dir: 0x%x set inline_dots", nid); } } } +skip_dot_fix: i_gc_failures = le16_to_cpu(node_blk->i.i_gc_failures); diff --git a/fsck/main.c b/fsck/main.c index 43b807ff..83f64464 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -908,6 +908,7 @@ static int do_fsck(struct f2fs_sb_info *sbi) u32 flag = le32_to_cpu(ckpt->ckpt_flags); u32 blk_cnt; struct f2fs_compr_blk_cnt cbc; + struct child_info child = { 0 }; errcode_t ret; fsck_init(sbi); @@ -973,8 +974,9 @@ static int do_fsck(struct f2fs_sb_info *sbi) if (fsck_sanity_check_nat(sbi, sbi->root_ino_num)) fsck_chk_root_inode(sbi); + child.p_ino = sbi->root_ino_num; fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num, - F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, NULL); + F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, &child); fsck_chk_quota_files(sbi); ret = fsck_verify(sbi);