# SPDX-License-Identifier: CDDL-1.0
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.cfg

#
# Compare the value of copies property with specified value
# $1, the dataset name
# $2, the expected copies value
#
function cmp_prop
{
	typeset ds=$1
	typeset	val_expect=$2
	typeset val_actual

	val_actual=$(get_prop copies $ds)
	if [[ $val_actual != $val_expect ]]; then
		log_fail "Expected value ($val_expect) != actual value " \
		    "($val_actual)"
	fi
}

#
# Check the used space is charged correctly
# $1, the number of used space
# $2, the expected common factor between the used space and the file space
#
function check_used
{
	typeset charged_spc=$1
	typeset -i used
	typeset -i expected_cfactor=$2
	typeset -i cfactor
	typeset -i fsize=${FILESIZE%[m|M]}

	((used = $charged_spc / 1024 / 1024))
	((cfactor = used / fsize))
	if ((cfactor != expected_cfactor)); then
		log_fail "The space is not charged correctly while setting" \
		    "copies as $expected_cfactor."
	fi
}

#
# test ncopies on volume
# $1  test type zfs|ufs|ext2
# $2  copies
# $3  mntp for ufs|ext2 test
function do_vol_test
{
	typeset type=$1
	typeset copies=$2
	typeset mntp=$3

	vol=$TESTPOOL/$TESTVOL1
	vol_b_path=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL1

	log_must zfs create -V $VOLSIZE -o compression=off -o copies=$copies \
	    $vol
	log_must zfs set refreservation=none $vol
	block_device_wait $vol_b_path

	case "$type" in
	"ext2")
		if is_freebsd; then
			log_unsupported "ext2 test not implemented for freebsd"
		fi
		log_must eval "new_fs $vol_b_path >/dev/null 2>&1"
		log_must mount -o rw $vol_b_path $mntp
		;;
	"ufs")
		if is_linux; then
			log_unsupported "ufs test not implemented for linux"
		fi
		log_must eval "new_fs $vol_b_path >/dev/null 2>&1"
		log_must mount $vol_b_path $mntp
		;;
	"zfs")
		if is_freebsd; then
			# Pool creation on zvols is forbidden by default.
			# Save and restore the current setting.
			typeset _saved=$(get_tunable VOL_RECURSIVE)
			log_must set_tunable64 VOL_RECURSIVE 1 # Allow
			zpool create $TESTPOOL1 $vol_b_path
			typeset _zpool_create_result=$?
			log_must set_tunable64 VOL_RECURSIVE $_saved # Restore
			log_must test $_zpool_create_result = 0
		else
			log_must zpool create $TESTPOOL1 $vol_b_path
		fi
		log_must zfs create -o compression=off $TESTPOOL1/$TESTFS1
		sync_pool $TESTPOOL1
		;;
	*)
		log_unsupported "$type test not implemented"
		;;
	esac

	sync_pool $TESTPOOL
	pre_used=$(get_prop used $vol)

	if [[ $type == "zfs" ]]; then
		log_must mkfile $FILESIZE /$TESTPOOL1/$TESTFS1/$FILE
		sync_pool $TESTPOOL1
	else
		log_must mkfile $FILESIZE $mntp/$FILE
		log_must sync
	fi

	sync_pool $TESTPOOL
	post_used=$(get_prop used $vol)

	((used = post_used - pre_used))
	((nfilesize = copies * ${FILESIZE%m}))
	if ((used < nfilesize)); then
		log_fail "The space is not charged correctly while setting" \
		    "copies as $copies ($used < $nfilesize)" \
		    "pre=${pre_used} post=${post_used}"
	fi

	if [[ $type == "zfs" ]]; then
		log_must zpool destroy $TESTPOOL1
	else
		log_must umount $mntp
	fi

	# Ubuntu 20.04 wants a sync here
	log_must sync
	log_must zfs destroy $vol
}
