#!/bin/sh
# Copyright (c), 2024, Huawei Technologies Co, Ltd.
# Author: Zhihao Cheng <chengzhihao1@huawei.com>
#
# Test Description:
# Do many cycles of mount/fsstress/umount/fsck/mount, check whether the
# filesystem content before fsck and after fsck are consistent.
# Running time: 10h

TESTBINDIR=/usr/libexec/mtd-utils
source $TESTBINDIR/common.sh

ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB 512-sub-page

function run_test()
{
	encryption=$1
	modprobe nandsim id_bytes=$ID
	mtdnum="$(find_mtd_device "$nandsim_patt")"
	flash_eraseall /dev/mtd$mtdnum

	dmesg -c > /dev/null

	modprobe ubi mtd="$mtdnum,2048" || fatal "modprobe ubi fail"
	ubimkvol -N vol_test -m -n 0 /dev/ubi$UBI_NUM || fatal "mkvol fail"
	modprobe ubifs || fatal "modprobe ubifs fail"

	echo "Do cycle mount+umount+fsck+check_fs_content test ($encryption)"

	if [[ "$encryption" == "encrypted" ]]; then
		encryption_gen_key
	fi

	round=0
	while [[ $round -lt 20 ]]
	do
		echo "---------------------- ROUND $round ----------------------"
		let round=$round+1

		mount_ubifs $DEV $MNT "noauthentication" "noatime" || fatal "mount ubifs fail"
		if [[ "$encryption" == "encrypted" ]]; then
			encryption_set_key $MNT
		fi

		per=`df -Th | grep ubifs | awk '{print $6}'`;
		if [[ ${per%?} -gt 95 ]]; then
			# Used > 95%
			echo "Clean files"
			rm -rf $MNT/*
			check_err_msg
		fi

		fsstress -d $MNT -l0 -p4 -n10000 &

		sleep $((RANDOM % 30))

		ps -e | grep -w fsstress > /dev/null 2>&1
		while [ $? -eq 0 ]
		do
			killall -9 fsstress > /dev/null 2>&1
			sleep 1
			ps -e | grep -w fsstress > /dev/null 2>&1
		done

		per=`df -Th | grep ubifs | awk '{print $6}'`;
		if [[ ${per%?} -gt 95 ]]; then
			dmesg -c > /dev/null # The ENOSPC error messages may exist
		else
			check_err_msg # Make sure new operations are okay after fsck
		fi
		sync

		# Record filesystem information
		rm -f $TMP_FILE 2>/dev/null
		read_dir $MNT "md5sum"

		while true
		do
			res=`mount | grep "$MNT"`
			if [[ "$res" == "" ]]
			then
				break;
			fi
			umount $MNT
			sleep 0.1
		done

		fsck.ubifs -a $DEV 2>&1 > $LOG_FILE
		res=$?
		cat $LOG_FILE
		if [[ $res != $FSCK_OK ]]
		then
			# The lpt nodes could be parsed incorrectly because the lpt disk
			# layout is too simple. See details in
			# https://lore.kernel.org/linux-mtd/97ca7fe4-4ad4-edd1-e97a-1d540aeabe2d@huawei.com/
			log=`cat $LOG_FILE | grep "dbg_check_ltab_lnum: invalid empty space in LEB"`
			if [[ "$log" == "" ]]; then
				fatal "fsck fail $res"
			fi
			if [[ $res != $FSCK_NONDESTRUCT ]]; then
				fatal "fsck fail $res"
			fi
		fi

		enable_chkfs

		mount_ubifs $DEV $MNT "noauthentication" "noatime"
		res=$?
		if [[ $res != 0 ]]
		then
			fatal "mount fail $res"
		fi

		if [[ "$encryption" == "encrypted" ]]; then
			encryption_set_key $MNT
		fi

		du -sh $MNT > /dev/null  # Ensure that all files are accessible
		ret=$?
		if [[ $ret != 0 ]]; then
			fatal "Cannot access all files"
		fi
		check_err_msg

		# Check filesystem information
		parse_dir "md5sum"
		rm -f $TMP_FILE 2>/dev/null

		umount $MNT
		res=$?
		if [[ $res != 0 ]]
		then
			fatal "unmount fail $res"
		fi

		check_err_msg

		disable_chkfs
	done

	modprobe -r ubifs
	modprobe -r ubi
	modprobe -r nandsim
}

check_fsstress
start_t=$(date +%s)
for encryption in "encrypted" "noencrypted"; do
	run_test $encryption
done
end_t=$(date +%s)
time_cost=$(( end_t - start_t ))
echo "Success, cost $time_cost seconds"
exit 0
