xref: /spdk/test/bdev/bdev_raid.sh (revision 877573897ad52be4fa8989f7617bd655b87e05c4)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2019 Intel Corporation
4#  All rights reserved.
5#
6testdir=$(readlink -f $(dirname $0))
7rootdir=$(readlink -f $testdir/../..)
8rpc_server=/var/tmp/spdk-raid.sock
9tmp_file=$SPDK_TEST_STORAGE/raidrandtest
10
11source $rootdir/test/common/autotest_common.sh
12source $testdir/nbd_common.sh
13
14rpc_py="$rootdir/scripts/rpc.py -s $rpc_server"
15
16function raid_unmap_data_verify() {
17	if hash blkdiscard; then
18		local nbd=$1
19		local rpc_server=$2
20		local blksize
21		blksize=$(lsblk -o LOG-SEC $nbd | grep -v LOG-SEC | cut -d ' ' -f 5)
22		local rw_blk_num=4096
23		local rw_len=$((blksize * rw_blk_num))
24		local unmap_blk_offs=(0 1028 321)
25		local unmap_blk_nums=(128 2035 456)
26		local unmap_off
27		local unmap_len
28
29		# data write
30		dd if=/dev/urandom of=$tmp_file bs=$blksize count=$rw_blk_num
31		dd if=$tmp_file of=$nbd bs=$blksize count=$rw_blk_num oflag=direct
32		blockdev --flushbufs $nbd
33
34		# confirm random data is written correctly in raid0 device
35		cmp -b -n $rw_len $tmp_file $nbd
36
37		for ((i = 0; i < ${#unmap_blk_offs[@]}; i++)); do
38			unmap_off=$((blksize * ${unmap_blk_offs[$i]}))
39			unmap_len=$((blksize * ${unmap_blk_nums[$i]}))
40
41			# data unmap on tmp_file
42			dd if=/dev/zero of=$tmp_file bs=$blksize seek=${unmap_blk_offs[$i]} count=${unmap_blk_nums[$i]} conv=notrunc
43
44			# data unmap on raid bdev
45			blkdiscard -o $unmap_off -l $unmap_len $nbd
46			blockdev --flushbufs $nbd
47
48			# data verify after unmap
49			cmp -b -n $rw_len $tmp_file $nbd
50		done
51	fi
52
53	return 0
54}
55
56function on_error_exit() {
57	if [ -n "$raid_pid" ]; then
58		killprocess $raid_pid
59	fi
60
61	rm -f $tmp_file
62	print_backtrace
63	exit 1
64}
65
66function configure_raid_bdev() {
67	local raid_level=$1
68	rm -rf $testdir/rpcs.txt
69
70	cat <<- EOL >> $testdir/rpcs.txt
71		bdev_malloc_create 32 512 -b Base_1
72		bdev_malloc_create 32 512 -b Base_2
73		bdev_raid_create -z 64 -r $raid_level -b "Base_1 Base_2" -n raid
74	EOL
75	$rpc_py < $testdir/rpcs.txt
76
77	rm -rf $testdir/rpcs.txt
78}
79
80function raid_function_test() {
81	local raid_level=$1
82	if [ $(uname -s) = Linux ] && modprobe -n nbd; then
83		local nbd=/dev/nbd0
84		local raid_bdev
85
86		modprobe nbd
87		$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
88		raid_pid=$!
89		echo "Process raid pid: $raid_pid"
90		waitforlisten $raid_pid $rpc_server
91
92		configure_raid_bdev $raid_level
93		raid_bdev=$($rpc_py bdev_raid_get_bdevs online | jq -r '.[0]["name"] | select(.)')
94		if [ $raid_bdev = "" ]; then
95			echo "No raid0 device in SPDK app"
96			return 1
97		fi
98
99		nbd_start_disks $rpc_server $raid_bdev $nbd
100		count=$(nbd_get_count $rpc_server)
101		if [ $count -ne 1 ]; then
102			return 1
103		fi
104
105		raid_unmap_data_verify $nbd $rpc_server
106
107		nbd_stop_disks $rpc_server $nbd
108		count=$(nbd_get_count $rpc_server)
109		if [ $count -ne 0 ]; then
110			return 1
111		fi
112
113		killprocess $raid_pid
114	else
115		echo "skipping bdev raid tests."
116	fi
117
118	return 0
119}
120
121function raid_state_function_test() {
122	local raid_level=$1
123	local raid_bdev
124	local base_bdev1="Non_Existed_Base_1"
125	local base_bdev2="Non_Existed_Base_2"
126	local raid_bdev_name="Existed_Raid"
127
128	$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
129	raid_pid=$!
130	echo "Process raid pid: $raid_pid"
131	waitforlisten $raid_pid $rpc_server
132
133	# Step1: create a RAID bdev with no base bdevs
134	# Expect state: CONFIGURING
135	$rpc_py bdev_raid_create -z 64 -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
136	raid_bdev=$($rpc_py bdev_raid_get_bdevs configuring | jq -r '.[0]["name"]')
137	if [ $raid_bdev != $raid_bdev_name ]; then
138		echo "No raid device in SPDK app"
139		return 1
140	else
141		# Test: Delete the RAID bdev successfully
142		$rpc_py bdev_raid_delete $raid_bdev_name
143	fi
144
145	# Step2: create one base bdev and add to the RAID bdev
146	# Expect state: CONFIGURING
147	$rpc_py bdev_raid_create -z 64 -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
148	$rpc_py bdev_malloc_create 32 512 -b $base_bdev1
149	waitforbdev $base_bdev1
150	raid_bdev=$($rpc_py bdev_raid_get_bdevs configuring | jq -r '.[0]["name"]')
151	if [ $raid_bdev != $raid_bdev_name ]; then
152		echo "$raid_bdev_name is not in CONFIGURING state"
153		$rpc_py bdev_malloc_delete $base_bdev1
154		$rpc_py bdev_raid_delete $raid_bdev_name
155		return 1
156	else
157		# Test: Delete the RAID bdev successfully
158		$rpc_py bdev_raid_delete $raid_bdev_name
159	fi
160
161	# Step3: create another base bdev and add to the RAID bdev
162	# Expect state: ONLINE
163	$rpc_py bdev_raid_create -z 64 -r $raid_level -b "$base_bdev1 $base_bdev2" -n $raid_bdev_name
164	$rpc_py bdev_malloc_create 32 512 -b $base_bdev2
165	waitforbdev $base_bdev2
166	raid_bdev=$($rpc_py bdev_raid_get_bdevs online | jq -r '.[0]["name"]')
167	if [ $raid_bdev != $raid_bdev_name ]; then
168		echo "$raid_bdev_name is not in ONLINE state"
169		$rpc_py bdev_malloc_delete $base_bdev1
170		$rpc_py bdev_malloc_delete $base_bdev2
171		$rpc_py bdev_raid_delete $raid_bdev_name
172		return 1
173	fi
174
175	# Step4: delete one base bdev from the RAID bdev
176	# Expect state: OFFLINE
177	$rpc_py bdev_malloc_delete $base_bdev2
178	raid_bdev=$($rpc_py bdev_raid_get_bdevs offline | jq -r '.[0]["name"]')
179	if [ $raid_bdev != $raid_bdev_name ]; then
180		echo "$raid_bdev_name is not in OFFLINE state"
181		$rpc_py bdev_malloc_delete $base_bdev1
182		$rpc_py bdev_raid_delete $raid_bdev_name
183		return 1
184	fi
185
186	# Step5: delete last base bdev from the RAID bdev
187	# Expect state: removed from system
188	$rpc_py bdev_malloc_delete $base_bdev1
189	raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[0]["name"] | select(.)')
190	if [ -n "$raid_bdev" ]; then
191		echo "$raid_bdev_name is not removed"
192		$rpc_py bdev_raid_delete $raid_bdev_name
193		return 1
194	fi
195
196	killprocess $raid_pid
197
198	return 0
199}
200
201trap 'on_error_exit;' ERR
202
203raid_function_test raid0
204raid_function_test concat
205raid_state_function_test raid0
206raid_state_function_test concat
207
208rm -f $tmp_file
209