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