#!/bin/bash
# - fs
# - fs_type
# - mkfs
# - mount
# - mount_option
# - nr_tmpfs
# mount_to
# mount_bind
# persist

# normal disks will mount to $mount_points/{nfs, fs}/
# mount_to is for mount disks to specified directory.
#	use it by:
#	  disk:
#         - 1HDD
#         fs:
#         - xfs
#         mount_to: /mnt/sda
#      or
#         disk:
#         - 2HDD
#         fs:
#         - xfs
#         mount_to:
#         - /mnt/sda
#         - /mnt/sdb

# mount_bind will mount only the first mount point of mount_to array, and mount all the rest mount points of mount_to array bind to the first mount point,
# if $mount_bind=true, will call function mount_bind() in this script,
# if $mount_bind is not true or not exist, will not call function mount_bind(), just mount the every disk to every mount point.
# This script supports 2 NFS mount schemes:
# fs1: followup scripts will see NFS mount_points only
# fs2: followup scripts will see NFS mount_points as well as original mount_points

# fs_type can avoid $LKP_SRC/params/fs parse
# fs1:
#    fs_type:
#    - ext4
#    - xfs
# mount_to: /mnt/sda
#
# if you want keep original data of your devices, then add persist field in your job.yaml, like the following:
# fs1:
#    fs_type: ext4
# persist: true

: ${fs:=$fs_type}
[ -n "$fs" ] || exit 0

. $LKP_SRC/lib/reproduce-log.sh
. $LKP_SRC/lib/fs_ext.sh
. $LKP_SRC/lib/http.sh

[ -n "$mount_option" ] && mount_option="-o $mount_option"

def_mount=
def_mkfs=
fs_options() {
	case $fs in
	xfs)
		def_mount="-o inode64"
		[ "${raid_level#*raid}" != "$raid_level" ] && [ "$nr_partitions" -gt 1 ] && {
			def_mount="${def_mount},logbsize=262144"
			def_mkfs="-f -d agcount=$nr_partitions"
		}
		ensure_mkfs='-f'
		;;
	ext*)
		ensure_mkfs='-q -F'
		;;
	btrfs)
		;;
	f2fs)
		modprobe f2fs 2>/dev/null
		;;
	nfsv3)
		def_mount="-o vers=3"
		fs="nfs"
		;;
	nfsv4)
		def_mount="-o vers=4"
		fs="nfs"
		;;
	# https://www.mankier.com/8/mount.cifs
	cifs)
		;;
	smbv2)
		def_mount="-o vers=2.0"
		;;
	smbv2p1)
		def_mount="-o vers=2.1"
		;;
	smbv3)
		def_mount="-o vers=3.0"
		;;
	smbv3p02)
		def_mount="-o vers=3.02"
		;;
	smbv3p11)
		def_mount="-o vers=3.11"
		;;
	cifs*|smb*)
		die "unknow cifs/smb version"
		;;
	udf)
		;;
	ocfs2)
		ensure_mkfs='-q -F'
		;;
	esac
}

is_btrfs_raid_levels() {
	[ "$fs" = 'btrfs' ] && [ "$raid_level" = 'braid0' -o \
				 "$raid_level" = 'braid1' -o \
				 "$raid_level" = 'braid5' -o \
				 "$raid_level" = 'braid6' -o \
				 "$raid_level" = 'braid10' ]
}

make_fs() {
	is_btrfs_raid_levels && {
		log_cmd mkfs.btrfs --data ${raid_level#b} -m ${raid_level#b} $mkfs $ensure_mkfs $partitions || exit
		return
	}

	[ "$fs" = 'ocfs2' ] && {
		start_o2cb || exit
	}

	local pids=
	for dev in $bdevs
	do
		log_cmd mkfs -t $fs ${mkfs:-$def_mkfs} $ensure_mkfs $dev &
		pids="${pids} $! "
	done

	local pid
	for pid in $pids; do
		wait $pid || exit
	done
}

probe_filesystem()
{
	local fs=$1
	grep -w $fs /proc/filesystems || log_cmd modprobe $fs
}

mount_fs() {
	local bdevs_num=0
	for dev in $bdevs
	do
		local mnt
		bdevs_num=$(($bdevs_num + 1))

		[ -n "$mount_to" ] && mnt=$(echo $mount_to | awk "{print \$${bdevs_num}}")
		mnt=${mnt:-/fs/$(basename $dev)}
		log_cmd mkdir -p $mnt
		probe_filesystem $fs
		log_cmd mount -t $fs ${mount:-$def_mount} $mount_option $dev $mnt || exit
		mount_points="${mount_points}$mnt "
	done

	if [ "$mount_bind" == "true" ]; then
		mount_bind
	fi
}

mount_bind()
{
	mount_array=($mount_to)
	num=$(echo ${#mount_array[@]})
	[ "$num" -gt "1" ] && {
		for i in ${!mount_array[@]}
		do
			[ "$i" == "0" ] && continue
			log_cmd mkdir -p ${mount_array[$i]}
			mount --bind ${mount_array[0]} ${mount_array[$i]}
		done
	}
}

if is_btrfs_raid_levels; then
	bdevs="${partitions%% *}"
else
	bdevs="$partitions"
fi

fs_options

case $fs in
	nfs)
		start_nfsd $mount_points
		mount_local_nfs $mount_points
		[ "${0#*fs1}" != "$0" ] && mount_points=
		;;
	cifs|smb*)
		start_smbd $mount_points
		mount_local_cifs $mount_points
		[ "${0#*fs1}" != "$0" ] && mount_points=
		;;


	tmpfs)
		: ${nr_tmpfs:=1}
		mount_tmpfs $nr_tmpfs
		;;

	*)
		. $LKP_SRC/lib/fs_ext.sh
		[ "$persist" == "true" ] || {
			if [ -n "$raid_device" ] || [ -n "$LKP_LOCAL_RUN" ]; then
				destroy_fs
			else
				destroy_devices
			fi
			make_fs
		}
		mount_fs || {
			set_job_state 'mount_fs_failed'
			exit 1
		}
		;;
esac

cat > "$TMP_RESULT_ROOT/post-run.fs" <<EOF

#!/bin/sh

umount_fs() {
	for mt in $nfs_mount_points $mount_points; do
		mountpoint -q \$mt && umount \$mt
	done
}

umount_fs
EOF

if [ "${0#*fs2}" != "$0" ]; then
	fs_key=fs2
else
	fs_key=fs
fi

cat >> $TMP/env.yaml <<EOF

# setup/$fs_key
$fs_key: $fs
mount_points: $nfs_mount_points $cifs_mount_points $mount_points
cifs_mount_points: $cifs_mount_points
cifs_server_paths: $cifs_server_paths
nfs_mount_points: $nfs_mount_points
nfs_export_paths: $nfs_export_paths
EOF
