#!/bin/sh
# Copyright (c), 2024, Huawei Technologies Co, Ltd.
# Author: Zhihao Cheng <chengzhihao1@huawei.com>
#
# Test Description:
# Do many cycles of mount/fsstress/powercut/umount/fsck/mount, check whether
# mount is successful.
# Running time: 9h

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

ID="0x20,0xa7,0x00,0x26" # 4G 256KB 4KB 2KB-sub-page

function run_test()
{
	local encryption=$1

	echo "Do cycle mount+powercut+fsck+umount($encryption) test"
	modprobe nandsim id_bytes=$ID
	mtdnum="$(find_mtd_device "$nandsim_patt")"
	flash_eraseall /dev/mtd$mtdnum

	dmesg -c > /dev/null

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

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

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

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

		if [[ $(($round % 30)) == 0 ]]
		then
			echo "Clean files"
			rm -rf $MNT/*
			check_err_msg
		fi

		fsstress -d $MNT -l0 -p4 -n10000 &
		sleep $((RANDOM % 30))

		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
		powercut

		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

		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
			# Powercut during layout_leb_in_gaps may change index
			# LEBs without updating LPT.
			idx_log=`cat $LOG_FILE | grep "Inconsistent properties" | grep "is_idx 1"`
			# 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/
			lpt_log=`cat $LOG_FILE | grep "dbg_check_ltab_lnum: invalid empty space in LEB"`
			if [[ "$idx_log" == "" ]] && [[ "$lpt_log" == "" ]]; then
				fatal "fsck fail $res"
			fi
			if [[ $res != $FSCK_NONDESTRUCT ]]; then
				fatal "fsck fail $res"
			fi
		fi

		dmesg -c > /dev/null # powercut could reproduce error messages

		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  # Make sure all files are accessible
		ret=$?
		if [[ $ret != 0 ]]; then
			fatal "Cannot access all files"
		fi
		check_err_msg

		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)
run_test "encrypted"
run_test "noencrypted"
end_t=$(date +%s)
time_cost=$(( end_t - start_t ))
echo "Success, cost $time_cost seconds"
exit 0
