diff mbox series

[f2fs-dev,1/2] fsck.f2fs: fix to detect double '.' or '..'

Message ID 20240904031746.1262403-1-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
If there are double '.' or '..' dirents in directory, fsck.f2fs won't
detect and repaire the issue correctly, fix it.

Reviewed-by: Sheng Yong <shengyong@oppo.com>
Signed-off-by: Chao Yu <chao@kernel.org>
---
 fsck/fsck.c       | 55 +++++++++++++++++++++++++++++++----------------
 fsck/fsck.h       |  3 ++-
 include/f2fs_fs.h |  6 ++++++
 3 files changed, 45 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/fsck/fsck.c b/fsck/fsck.c
index a18bee9..54ddc11 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -1307,10 +1307,10 @@  skip_blkcnt_fix:
 						nid, i_links, child.links);
 			}
 		}
-		if (child.dots < 2 &&
+		if ((child.dot == 0 || child.dotdot == 0) &&
 				!(node_blk->i.i_inline & F2FS_INLINE_DOTS)) {
-			ASSERT_MSG("ino: 0x%x dots: %u",
-					nid, child.dots);
+			ASSERT_MSG("ino: 0x%x dot: %u, dotdot: %u",
+					nid, child.dot, child.dotdot);
 			if (c.fix_on) {
 				node_blk->i.i_inline |= F2FS_INLINE_DOTS;
 				need_fix = 1;
@@ -1862,26 +1862,45 @@  static int __chk_dentries(struct f2fs_sb_info *sbi, int casefolded,
 
 		/* Becareful. 'dentry.file_type' is not imode. */
 		if (ftype == F2FS_FT_DIR) {
-			if ((name[0] == '.' && name_len == 1) ||
-				(name[0] == '.' && name[1] == '.' &&
-							name_len == 2)) {
-				ret = __chk_dots_dentries(sbi, casefolded, &dentry[i],
-					child, name, name_len, &filenames[i],
-					enc_name);
-				switch (ret) {
-				case 1:
+			enum dot_type dot_type = NON_DOT;
+
+			if (name[0] == '.' && name_len == 1)
+				dot_type = TYPE_DOT;
+			else if (name[0] == '.' && name[1] == '.' &&
+						name_len == 2)
+				dot_type = TYPE_DOTDOT;
+
+			if (dot_type != NON_DOT) {
+				bool need_del = false;
+
+				DBG(3, "i:%u, dot_type:%u, ino:%u, p:%u, pp:%u\n",
+					i, dot_type, dentry[i].ino,
+					child->p_ino, child->pp_ino);
+
+				ret = __chk_dots_dentries(sbi, casefolded,
+					&dentry[i], child, name, name_len,
+					&filenames[i], enc_name);
+				if (ret)
 					fixed = 1;
-					fallthrough;
-				case 0:
-					child->dots++;
-					break;
+
+				if (dot_type == TYPE_DOT) {
+					if (child->dot == 0)
+						child->dot++;
+					else
+						need_del = true;
+				} else if (dot_type == TYPE_DOTDOT) {
+					if (child->dotdot == 0)
+						child->dotdot++;
+					else
+						need_del = true;
 				}
 
-				if (child->dots > 2) {
-					ASSERT_MSG("More than one '.' or '..', should delete the extra one\n");
+				if (need_del) {
+					ASSERT_MSG("More than one '%s', should delete the extra one, i: %u, ino:%u",
+						dot_type == TYPE_DOT ? "." : "..",
+						i, dentry[i].ino);
 					nullify_dentry(&dentry[i], i,
 						       &filenames[i], &bitmap);
-					child->dots--;
 					fixed = 1;
 				}
 
diff --git a/fsck/fsck.h b/fsck/fsck.h
index a8f187e..efccfbc 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -70,7 +70,8 @@  struct child_info {
 	u32 links;
 	u32 files;
 	u32 pgofs;
-	u8 dots;
+	u8 dot;
+	u8 dotdot;
 	u8 dir_level;
 	u32 p_ino;		/* parent ino */
 	char p_name[F2FS_NAME_LEN + 1]; /* parent name */
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 15a1c82..0b6777a 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -1429,6 +1429,12 @@  enum FILE_TYPE {
 	F2FS_FT_LAST_FILE_TYPE = F2FS_FT_XATTR,
 };
 
+enum dot_type {
+	NON_DOT,
+	TYPE_DOT,
+	TYPE_DOTDOT
+};
+
 #define LINUX_S_IFMT  00170000
 #define LINUX_S_IFREG  0100000
 #define LINUX_S_IFDIR  0040000