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