diff mbox series

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

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

Commit Message

Chao Yu Feb. 25, 2025, 9:36 a.m. UTC
fsck.f2fs missed to check and repair zeroed i_links for char, block,
fifo, sock, symlink and regular inode, fix it.

Tested w/ below testcase:

dev=/dev/vda
mp=/mnt/f2fs
for ((i=0;i<14;i++)) do
	echo "testcase #"$i
	mkfs.f2fs -f $dev >/dev/null 2>&1
	if [ $? != 0 ]; then
		exit
	fi
	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 & sleep 2
		fuser -k $mp/sock
		nlink=0
	elif [ $i == 6 ]; then
		ln -s file symlink
		nlink=0
	elif [ $i == 7 ]; then
		# orphan inode
		touch atomic
		f2fs_io write 1 0 1 zero atomic_commit ./atomic 2000 &
		rm atomic
		sync
		f2fs_io shutdown 2 ./
		nlink=1
		sleep 2
	elif [ $i == 8 ]; then
		# hardlink on file
		touch file
		ln file hardlink
		nlink=0
	elif [ $i == 9 ]; then
		# hardlink on charactor
		mknod charactor c 9 0
		ln charactor hardlink
		nlink=0
	elif [ $i == 10 ]; then
		# hardlink on blockdev
		mknod blockdev b 8 0
		ln blockdev hardlink
		nlink=0
	elif [ $i == 11 ]; then
		# hardlink on pipe
		mkfifo pipe
		ln pipe hardlink
		nlink=0
	elif [ $i == 12 ]; then
		# hardlink on socket
		socket -s $mp/sock & sleep 2
		fuser -k $mp/sock
		ln sock hardlink
		nlink=0
	elif [ $i == 13 ]; then
		# hardlink on symlink
		ln -s file symlink
		ln symlink hardlink
		nlink=0
	fi

	cd ~/
	umount $mp

	inject.f2fs --node --mb i_links --nid 4 --val $nlink $dev
	if [ $? != 0 ]; then
		exit
	fi

	fsck.f2fs -f $dev
	if [ $? != 1 ]; then
		exit
	fi
	fsck.f2fs $dev
	if [ $? != 0 ]; then
		exit
	fi

	mount $dev $mp
	stat $mp/*
	umount $mp
done

Signed-off-by: Chao Yu <chao@kernel.org>
---
v2:
- update testcase to cover hardlink of non-dir inode
- fix zeroed i_links only
 fsck/fsck.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/fsck/fsck.c b/fsck/fsck.c
index aa3fb97..8155cbd 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -942,6 +942,22 @@  check_next:
 		if (f2fs_test_main_bitmap(sbi, ni->blk_addr) == 0) {
 			f2fs_set_main_bitmap(sbi, ni->blk_addr,
 							CURSEG_WARM_NODE);
+
+			if (i_links == 0 && (ftype == F2FS_FT_CHRDEV ||
+				ftype == F2FS_FT_BLKDEV ||
+				ftype == F2FS_FT_FIFO ||
+				ftype == F2FS_FT_SOCK ||
+				ftype == F2FS_FT_SYMLINK ||
+				ftype == F2FS_FT_REG_FILE)) {
+				ASSERT_MSG("ino: 0x%x ftype: %d has i_links: %u",
+							nid, ftype, i_links);
+				if (c.fix_on) {
+					node_blk->i.i_links = cpu_to_le32(1);
+					need_fix = 1;
+					FIX_MSG("ino: 0x%x ftype: %d fix i_links: %u -> 1",
+						nid, ftype, i_links);
+				}
+			}
 			if (i_links > 1 && ftype != F2FS_FT_ORPHAN &&
 					!is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
 				/* First time. Create new hard link node */