diff mbox series

[f2fs-dev] fsck.f2fs: support to repair corrupted i_links

Message ID 20250225042710.294342-1-chao@kernel.org (mailing list archive)
State Superseded
Headers show
Series [f2fs-dev] fsck.f2fs: support to repair corrupted i_links | expand

Commit Message

Chao Yu Feb. 25, 2025, 4:27 a.m. UTC
Previous, fsck.f2fs only support i_links check and repair for orphan
and directory inode, this patch starts to check and repair i_links for
char, block, fifo, sock, symlink and regular inode.

Tested w/ below testcase:

dev=/dev/vda
mp=/mnt/f2fs
for ((i=0;i<8;i++)) do
	mkfs.f2fs -f $dev
	mount $dev $mp
	cd $mp

	if [ $i == 0 ]; then
		touch file
		nlink=0
	elif [ $i == 1 ]; then
		mkdir dir
		nlink=1
	elif [ $i == 2 ]; then
		mknod charactor c 9 0
		nlink=0
	elif [ $i == 3 ]; then
		mknod blockdev b 8 0
		nlink=0
	elif [ $i == 4 ]; then
		mkfifo pipe
		nlink=0
	elif [ $i == 5 ]; then
		socket -s $mp/sock & fuser -k $mp/sock
		nlink=0
	elif [ $i == 6 ]; then
		ln -s file symlink
		nlink=0
	elif [ $i == 7 ]; then
		touch atomic
		f2fs_io write 1 0 1 zero atomic_commit ./atomic 2000 &
		rm atomic
		sync
		f2fs_io shutdown 2 ./
		nlink=1
		sleep 2
	fi

	cd ~/
	umount $mp

	inject.f2fs --node --mb i_links --nid 4 --val $nlink $dev

	fsck.f2fs -f $dev
	fsck.f2fs $dev
done

Signed-off-by: Chao Yu <chao@kernel.org>
---
 fsck/fsck.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/fsck/fsck.c b/fsck/fsck.c
index ef9662b..ce88cfe 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -902,7 +902,9 @@  void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 	int need_fix = 0;
 	int ret;
 	u32 cluster_size = 1 << node_blk->i.i_log_cluster_size;
+	u32 target_links;
 	bool is_aliasing = IS_DEVICE_ALIASING(&node_blk->i);
+	bool corrupted_nlink = false;
 
 	if (!compressed)
 		goto check_next;
@@ -1413,14 +1415,33 @@  skip_dot_fix:
 					nid, (unsigned long)F2FS_BLKSIZE);
 	}
 
-	if (ftype == F2FS_FT_ORPHAN && i_links) {
-		ASSERT_MSG("ino: 0x%x is orphan inode, but has i_links: %u",
-				nid, i_links);
+	if (ftype == F2FS_FT_ORPHAN) {
+		if (i_links) {
+			corrupted_nlink = true;
+			target_links = 0;
+		}
+	} else if (ftype == F2FS_FT_CHRDEV || ftype == F2FS_FT_BLKDEV ||
+			ftype == F2FS_FT_FIFO || ftype == F2FS_FT_SOCK ||
+			ftype == F2FS_FT_SYMLINK) {
+		if (i_links != 1) {
+			corrupted_nlink = true;
+			target_links = 1;
+		}
+	} else if (ftype == F2FS_FT_REG_FILE) {
+		if (i_links == 0) {
+			corrupted_nlink = true;
+			target_links = 1;
+		}
+	}
+
+	if (corrupted_nlink) {
+		ASSERT_MSG("ino: 0x%x ftype: %d has i_links: %u",
+					nid, ftype, i_links);
 		if (c.fix_on) {
-			node_blk->i.i_links = 0;
+			node_blk->i.i_links = cpu_to_le32(target_links);
 			need_fix = 1;
-			FIX_MSG("ino: 0x%x orphan_inode, i_links= 0x%x -> 0",
-					nid, i_links);
+			FIX_MSG("ino: 0x%x ftype: %d fix i_links: %u -> %u",
+				nid, ftype, i_links, target_links);
 		}
 	}