xref: /spdk/test/setup/devices.sh (revision dfb2950fd5b13ba0a2a2b533e3e534202a89de74)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2020 Intel Corporation
4#  All rights reserved.
5#
6testdir=$(readlink -f "$(dirname "$0")")
7rootdir=$(readlink -f "$testdir/../../")
8source "$testdir/common.sh"
9
10cleanup() {
11	cleanup_nvme
12	cleanup_dm
13
14	if [[ -b /dev/$test_disk ]]; then
15		wipefs --all "/dev/$test_disk"
16	fi
17}
18
19cleanup_nvme() {
20	if mountpoint -q "$nvme_mount"; then
21		umount "$nvme_mount"
22	fi
23
24	if [[ -b /dev/$nvme_disk_p ]]; then
25		wipefs --all "/dev/$nvme_disk_p"
26	fi
27	if [[ -b /dev/$nvme_disk ]]; then
28		wipefs --all "/dev/$nvme_disk"
29	fi
30}
31
32cleanup_dm() {
33	if mountpoint -q "$dm_mount"; then
34		umount "$dm_mount"
35	fi
36	if [[ -L /dev/mapper/$dm_name ]]; then
37		dmsetup remove --force "$dm_name"
38	fi
39	if [[ -b /dev/$pv0 ]]; then
40		wipefs --all "/dev/$pv0"
41	fi
42	if [[ -b /dev/$pv1 ]]; then
43		wipefs --all "/dev/$pv1"
44	fi
45}
46
47verify() {
48	local dev=$1
49	local mounts=$2
50	local mount_point=$3
51	local test_file=$4
52
53	local found=0
54
55	if [[ -n $test_file ]]; then
56		: > "$test_file"
57	fi
58
59	local pci status
60	while read -r pci _ _ status; do
61		if [[ $pci == "$dev" &&
62			$status == *"Active devices: "*"$mounts"* ]]; then
63			found=1
64		fi
65	done < <(PCI_ALLOWED="$dev" setup output config)
66	((found == 1))
67
68	[[ -n $mount_point ]] || return 0
69
70	# Does the mount still exist?
71	mountpoint -q "$mount_point"
72	# Does the test file still exist?
73	[[ -e $test_file ]]
74	rm "$test_file"
75}
76
77nvme_mount() {
78	# Agenda 1:
79	# - Create single partition on the nvme drive
80	# - Install ext4 fs on the first partition
81	# - Mount the partition
82	# - Run tests and check if setup.sh skipped
83	#   nvme controller given block device is
84	#   bound to.
85
86	# Agenda 2:
87	# - Install ext4 on the entire nvme drive
88	# - Mount the drive
89	#   Run tests and check if setup.sh skipped
90	#   nvme controller given block device is
91	#   bound to.
92
93	# Keep scope of all the variables global to make the cleanup process easier.
94
95	nvme_disk=$test_disk
96	nvme_disk_p=${nvme_disk}p1
97	nvme_mount=$SPDK_TEST_STORAGE/nvme_mount
98	nvme_dummy_test_file=$nvme_mount/test_nvme
99
100	# Agenda 1
101	partition_drive "$nvme_disk" 1
102	mkfs "/dev/$nvme_disk_p" "$nvme_mount"
103
104	verify \
105		"${blocks_to_pci["$nvme_disk"]}" \
106		"$nvme_disk:$nvme_disk_p" \
107		"$nvme_mount" \
108		"$nvme_dummy_test_file"
109
110	cleanup_nvme
111
112	# Agenda 2
113	mkfs "/dev/$nvme_disk" "$nvme_mount" 1024M
114
115	verify \
116		"${blocks_to_pci["$nvme_disk"]}" \
117		"$nvme_disk:$nvme_disk" \
118		"$nvme_mount" \
119		"$nvme_dummy_test_file"
120
121	# umount the nvme device and verify again - device should not be touched
122	# when a valid fs is still present.
123	umount "$nvme_mount"
124
125	verify "${blocks_to_pci["$nvme_disk"]}" "data@$nvme_disk" "" ""
126
127	# All done, final cleanup
128	cleanup_nvme
129}
130
131dm_mount() {
132	# Agenda:
133	#  - Create two partitions on the nvme drive
134	#  - Create dm device consisting of half of
135	#    the size of each partition.
136	#  - Install ext4 fs on the dm device
137	#  - Mount dm device
138	#  - Run tests and check if setup.sh skipped
139	#    nvme controller given block devices are
140	#    bound to.
141
142	# Keep scope of all the variables global to make the cleanup process easier.
143
144	pv=$test_disk
145	pv0=${pv}p1
146	pv1=${pv}p2
147
148	partition_drive "$pv"
149
150	dm_name=nvme_dm_test
151	dm_mount=$SPDK_TEST_STORAGE/dm_mount
152	dm_dummy_test_file=$dm_mount/test_dm
153
154	# Each partition is 1G in size, join their halves
155	dmsetup create "$dm_name" <<- DM_TABLE
156		0 1048576 linear /dev/$pv0 0
157		1048576 1048576 linear /dev/$pv1 0
158	DM_TABLE
159
160	for t in {1..5}; do
161		if [[ -e /dev/mapper/$dm_name ]]; then break; fi
162		sleep 1
163	done
164	[[ -e /dev/mapper/$dm_name ]]
165	dm=$(readlink -f "/dev/mapper/$dm_name")
166	dm=${dm##*/}
167
168	[[ -e /sys/class/block/$pv0/holders/$dm ]]
169	[[ -e /sys/class/block/$pv1/holders/$dm ]]
170
171	mkfs "/dev/mapper/$dm_name" "$dm_mount"
172
173	verify \
174		"${blocks_to_pci["$pv"]}" \
175		"$pv:$dm_name" \
176		"$dm_mount" \
177		"$dm_dummy_test_file"
178
179	# umount the dm device and verify again - device should not be
180	# touched when it's actively being hold, regardless if it's mounted
181	# or not.
182	umount "$dm_mount"
183
184	verify "${blocks_to_pci["$pv"]}" "holder@$pv0:$dm,holder@$pv1:$dm" "" ""
185
186	# All done, start tiding up
187	cleanup_dm
188}
189
190trap "cleanup" EXIT
191
192setup reset
193
194get_zoned_devs
195
196declare -a blocks=()
197declare -A blocks_to_pci=()
198min_disk_size=$((1024 ** 3 * 3)) # 3GB
199
200for block in "/sys/block/nvme"!(*c*); do
201	ctrl=${block##*/} ctrl=${ctrl%n*}
202	pci=$(< "/sys/class/nvme/$ctrl/address")
203	[[ ${zoned_devs[*]} == *"$pci"* ]] && continue
204	if ! block_in_use "${block##*/}" && (($(sec_size_to_bytes "${block##*/}") >= min_disk_size)); then
205		blocks+=("${block##*/}")
206		blocks_to_pci["${block##*/}"]=$pci
207	fi
208done
209((${#blocks[@]} > 0))
210
211declare -r test_disk=${blocks[0]}
212
213run_test "nvme_mount" nvme_mount
214run_test "dm_mount" dm_mount
215