diff mbox series

[f2fs-dev,2/2] fsck.f2fs: support to add missing '.' or '..' dirent

Message ID 20240904031746.1262403-2-chao@kernel.org (mailing list archive)
State New
Headers show
Series [f2fs-dev,1/2] fsck.f2fs: fix to detect double '.' or '..' | expand

Commit Message

Chao Yu Sept. 4, 2024, 3:17 a.m. UTC
Previously, once fsck.f2fs detects that directory missed '.' or
'..' dirent, it tags inode w/ F2FS_INLINE_DOTS flag, and expects
f2fs kernel module can repaire it online during it runs to lookup()
on target directory.

This patch abandons previous implementation, and do repaires directly.

Reviewed-by: Sheng Yong <shengyong@oppo.com>
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fsck/fsck.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
 fsck/main.c |  4 +++-
 2 files changed, 43 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 54ddc11..f8ea7f0 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -1307,17 +1307,52 @@  skip_blkcnt_fix:
 						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 8881936..4e0254d 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -892,6 +892,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);
@@ -957,8 +958,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);