#!/bin/bash
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2019 Ming Lei <ming.lei@redhat.com>
#
# Test userspace IO on NVMe loop device. Regression test for patch "block: fix
# segment calculation for passthrough IO".

. tests/nvme/rc

DESCRIPTION="test userspace IO via nvme-cli read/write interface"
QUICK=1

requires() {
	_nvme_requires
	_have_loop
	_require_nvme_trtype_is_fabrics
}

test_user_io()
{
	local disk="$1"
	local start=$2
	local cnt=$3
	local bs, size, img, img1

	bs="$(blockdev --getss "$disk")"
	size=$((cnt * bs))
	img="$(mktemp /tmp/blk_img_XXXXXX)"
	img1="$(mktemp /tmp/blk_img_XXXXXX)"

	dd if=/dev/urandom of="$img" bs="$bs" count="$cnt" status=none

	((cnt--))

	if ! nvme write --start-block="$start" --block-count="$cnt" \
		--data-size="$size" --data="$img" "$disk"; then
		return 1
	fi
	if ! nvme read --start-block="$start" --block-count="$cnt" \
		--data-size="$size" --data="$img1" "$disk"; then
		return 1
	fi

	diff -q -u "$img" "$img1"
	local res=$?

	rm -f "$img" "$img1"
	return $res
}

test() {
	echo "Running ${TEST_NAME}"

	_setup_nvmet

	local port
	local nvmedev
	local loop_dev
	local file_path="$TMPDIR/img"
	local subsys_name="blktests-subsystem-1"

	truncate -s "${nvme_img_size}" "${file_path}"

	loop_dev="$(losetup -f --show "${file_path}")"

	_create_nvmet_subsystem "${subsys_name}" "${loop_dev}" \
		 "91fdba0d-f87b-4c25-b80f-db7be1418b9e"
	port="$(_create_nvmet_port "${nvme_trtype}")"
	_add_nvmet_subsys_to_port "${port}" "${subsys_name}"

	_nvme_connect_subsys "${nvme_trtype}" "${subsys_name}"

	nvmedev=$(_find_nvme_dev "${subsys_name}")
	cat "/sys/block/${nvmedev}n1/uuid"
	cat "/sys/block/${nvmedev}n1/wwid"

	local dev="/dev/${nvmedev}n1"
	test_user_io "$dev" 1 512 > "$FULL" 2>&1 || echo FAIL
	test_user_io "$dev" 1 511 > "$FULL" 2>&1 || echo FAIL
	test_user_io "$dev" 1 513 > "$FULL" 2>&1 || echo FAIL
	test_user_io "$dev" 511 1024 > "$FULL" 2>&1 || echo FAIL
	test_user_io "$dev" 511 1023 > "$FULL" 2>&1 || echo FAIL
	test_user_io "$dev" 511 1025 > "$FULL" 2>&1 || echo FAIL

	_nvme_disconnect_subsys "${subsys_name}" >> "$FULL" 2>&1

	_remove_nvmet_subsystem_from_port "${port}" "${subsys_name}"
	_remove_nvmet_subsystem "${subsys_name}"
	_remove_nvmet_port "${port}"

	losetup -d "${loop_dev}"

	rm "${file_path}"

	echo "Test complete"
}
