]>
Commit | Line | Data |
---|---|---|
f2204ac2 | 1 | #!/usr/bin/env bash |
7b3cec95 | 2 | # SPDX-License-Identifier: LGPL-2.1-or-later |
f2204ac2 FS |
3 | # vi: ts=4 sw=4 tw=0 et: |
4 | ||
5 | set -eux | |
6 | set -o pipefail | |
7 | ||
d430e451 | 8 | # Check if all symlinks under /dev/disk/ are valid |
df72bd45 | 9 | # shellcheck disable=SC2120 |
de11005c FS |
10 | helper_check_device_symlinks() {( |
11 | set +x | |
a0560b93 | 12 | |
6df02597 | 13 | local dev link path paths target |
df72bd45 | 14 | |
677acd21 | 15 | [[ $# -gt 0 ]] && paths=("$@") || paths=("/dev/disk" "/dev/mapper") |
d430e451 | 16 | |
6df02597 FS |
17 | # Check if all given paths are valid |
18 | for path in "${paths[@]}"; do | |
19 | if ! test -e "$path"; then | |
20 | echo >&2 "Path '$path' doesn't exist" | |
21 | return 1 | |
22 | fi | |
23 | done | |
24 | ||
d430e451 FS |
25 | while read -r link; do |
26 | target="$(readlink -f "$link")" | |
a0560b93 | 27 | echo "$link -> $target" |
d430e451 FS |
28 | # Both checks should do virtually the same thing, but check both to be |
29 | # on the safe side | |
30 | if [[ ! -e "$link" || ! -e "$target" ]]; then | |
31 | echo >&2 "ERROR: symlink '$link' points to '$target' which doesn't exist" | |
32 | return 1 | |
33 | fi | |
34 | ||
35 | # Check if the symlink points to the correct device in /dev | |
36 | dev="/dev/$(udevadm info -q name "$link")" | |
37 | if [[ "$target" != "$dev" ]]; then | |
38 | echo >&2 "ERROR: symlink '$link' points to '$target' but '$dev' was expected" | |
39 | return 1 | |
40 | fi | |
df72bd45 | 41 | done < <(find "${paths[@]}" -type l) |
de11005c | 42 | )} |
d430e451 | 43 | |
f2204ac2 FS |
44 | testcase_megasas2_basic() { |
45 | lsblk -S | |
46 | [[ "$(lsblk --scsi --noheadings | wc -l)" -ge 128 ]] | |
47 | } | |
48 | ||
49 | testcase_nvme_basic() { | |
50 | lsblk --noheadings | grep "^nvme" | |
51 | [[ "$(lsblk --noheadings | grep -c "^nvme")" -ge 28 ]] | |
52 | } | |
53 | ||
54 | testcase_virtio_scsi_identically_named_partitions() { | |
55 | lsblk --noheadings -a -o NAME,PARTLABEL | |
56 | [[ "$(lsblk --noheadings -a -o NAME,PARTLABEL | grep -c "Hello world")" -eq $((16 * 8)) ]] | |
57 | } | |
58 | ||
d0cbad16 FS |
59 | testcase_multipath_basic_failover() { |
60 | local dmpath i path wwid | |
61 | ||
62 | # Configure multipath | |
63 | cat >/etc/multipath.conf <<\EOF | |
64 | defaults { | |
65 | # Use /dev/mapper/$WWN paths instead of /dev/mapper/mpathX | |
66 | user_friendly_names no | |
67 | find_multipaths yes | |
68 | enable_foreign "^$" | |
69 | } | |
70 | ||
71 | blacklist_exceptions { | |
72 | property "(SCSI_IDENT_|ID_WWN)" | |
73 | } | |
74 | ||
75 | blacklist { | |
76 | } | |
77 | EOF | |
78 | modprobe -v dm_multipath | |
79 | systemctl start multipathd.service | |
80 | systemctl status multipathd.service | |
81 | multipath -ll | |
cd37793d | 82 | udevadm settle |
d0cbad16 FS |
83 | ls -l /dev/disk/by-id/ |
84 | ||
85 | for i in {0..63}; do | |
86 | wwid="deaddeadbeef$(printf "%.4d" "$i")" | |
87 | path="/dev/disk/by-id/wwn-0x$wwid" | |
88 | dmpath="$(readlink -f "$path")" | |
89 | ||
90 | lsblk "$path" | |
91 | multipath -C "$dmpath" | |
92 | # We should have 4 active paths for each multipath device | |
93 | [[ "$(multipath -l "$path" | grep -c running)" -eq 4 ]] | |
94 | done | |
95 | ||
96 | # Test failover (with the first multipath device that has a partitioned disk) | |
97 | echo "${FUNCNAME[0]}: test failover" | |
98 | local device expected link mpoint part | |
99 | local -a devices | |
100 | mpoint="$(mktemp -d /mnt/mpathXXX)" | |
101 | wwid="deaddeadbeef0000" | |
102 | path="/dev/disk/by-id/wwn-0x$wwid" | |
103 | ||
104 | # All following symlinks should exists and should be valid | |
105 | local -a part_links=( | |
106 | "/dev/disk/by-id/wwn-0x$wwid-part2" | |
107 | "/dev/disk/by-partlabel/failover_part" | |
108 | "/dev/disk/by-partuuid/deadbeef-dead-dead-beef-000000000000" | |
109 | "/dev/disk/by-label/failover_vol" | |
110 | "/dev/disk/by-uuid/deadbeef-dead-dead-beef-111111111111" | |
111 | ) | |
14f9c81f | 112 | udevadm wait --settle --timeout=30 "${part_links[@]}" |
d0cbad16 FS |
113 | |
114 | # Choose a random symlink to the failover data partition each time, for | |
115 | # a better coverage | |
116 | part="${part_links[$RANDOM % ${#part_links[@]}]}" | |
117 | ||
118 | # Get all devices attached to a specific multipath device (in H:C:T:L format) | |
119 | # and sort them in a random order, so we cut off different paths each time | |
120 | mapfile -t devices < <(multipath -l "$path" | grep -Eo '[0-9]+:[0-9]+:[0-9]+:[0-9]+' | sort -R) | |
121 | if [[ "${#devices[@]}" -ne 4 ]]; then | |
122 | echo "Expected 4 devices attached to WWID=$wwid, got ${#devices[@]} instead" | |
123 | return 1 | |
124 | fi | |
125 | # Drop the last path from the array, since we want to leave at least one path active | |
126 | unset "devices[3]" | |
127 | # Mount the first multipath partition, write some data we can check later, | |
128 | # and then disconnect the remaining paths one by one while checking if we | |
129 | # can still read/write from the mount | |
130 | mount -t ext4 "$part" "$mpoint" | |
131 | expected=0 | |
132 | echo -n "$expected" >"$mpoint/test" | |
133 | # Sanity check we actually wrote what we wanted | |
134 | [[ "$(<"$mpoint/test")" == "$expected" ]] | |
135 | ||
136 | for device in "${devices[@]}"; do | |
137 | echo offline >"/sys/class/scsi_device/$device/device/state" | |
138 | [[ "$(<"$mpoint/test")" == "$expected" ]] | |
139 | expected="$((expected + 1))" | |
140 | echo -n "$expected" >"$mpoint/test" | |
141 | ||
142 | # Make sure all symlinks are still valid | |
14f9c81f | 143 | udevadm wait --settle --timeout=30 "${part_links[@]}" |
d0cbad16 FS |
144 | done |
145 | ||
146 | multipath -l "$path" | |
147 | # Three paths should be now marked as 'offline' and one as 'running' | |
148 | [[ "$(multipath -l "$path" | grep -c offline)" -eq 3 ]] | |
149 | [[ "$(multipath -l "$path" | grep -c running)" -eq 1 ]] | |
150 | ||
151 | umount "$mpoint" | |
152 | rm -fr "$mpoint" | |
153 | } | |
154 | ||
35497c7c FS |
155 | testcase_simultaneous_events() { |
156 | local blockdev part partscript | |
157 | ||
158 | blockdev="$(readlink -f /dev/disk/by-id/scsi-*_deadbeeftest)" | |
159 | partscript="$(mktemp)" | |
160 | ||
161 | if [[ ! -b "$blockdev" ]]; then | |
162 | echo "ERROR: failed to find the test SCSI block device" | |
163 | return 1 | |
164 | fi | |
165 | ||
166 | cat >"$partscript" <<EOF | |
167 | $(printf 'name="test%d", size=2M\n' {1..50}) | |
168 | EOF | |
169 | ||
170 | # Initial partition table | |
bc6bd62c | 171 | udevadm lock --device="$blockdev" sfdisk -q -X gpt "$blockdev" <"$partscript" |
35497c7c | 172 | |
ba669952 | 173 | # Delete the partitions, immediately recreate them, wait for udev to settle |
35497c7c FS |
174 | # down, and then check if we have any dangling symlinks in /dev/disk/. Rinse |
175 | # and repeat. | |
176 | # | |
177 | # On unpatched udev versions the delete-recreate cycle may trigger a race | |
178 | # leading to dead symlinks in /dev/disk/ | |
179 | for i in {1..100}; do | |
bc6bd62c YW |
180 | udevadm lock --device="$blockdev" sfdisk -q --delete "$blockdev" |
181 | udevadm lock --device="$blockdev" sfdisk -q -X gpt "$blockdev" <"$partscript" | |
35497c7c FS |
182 | |
183 | if ((i % 10 == 0)); then | |
14f9c81f | 184 | udevadm wait --settle --timeout=30 "$blockdev" |
35497c7c FS |
185 | helper_check_device_symlinks |
186 | fi | |
187 | done | |
188 | ||
189 | rm -f "$partscript" | |
190 | } | |
191 | ||
0203b2e4 FS |
192 | testcase_lvm_basic() { |
193 | local i part | |
194 | local vgroup="MyTestGroup$RANDOM" | |
195 | local devices=( | |
196 | /dev/disk/by-id/ata-foobar_deadbeeflvm{0..3} | |
197 | ) | |
198 | ||
199 | # Make sure all the necessary soon-to-be-LVM devices exist | |
200 | ls -l "${devices[@]}" | |
201 | ||
202 | # Add all test devices into a volume group, create two logical volumes, | |
203 | # and check if necessary symlinks exist (and are valid) | |
204 | lvm pvcreate -y "${devices[@]}" | |
205 | lvm pvs | |
206 | lvm vgcreate "$vgroup" -y "${devices[@]}" | |
207 | lvm vgs | |
208 | lvm vgchange -ay "$vgroup" | |
209 | lvm lvcreate -y -L 4M "$vgroup" -n mypart1 | |
210 | lvm lvcreate -y -L 8M "$vgroup" -n mypart2 | |
211 | lvm lvs | |
14f9c81f | 212 | udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" |
0203b2e4 | 213 | mkfs.ext4 -L mylvpart1 "/dev/$vgroup/mypart1" |
14f9c81f | 214 | udevadm wait --settle --timeout=30 "/dev/disk/by-label/mylvpart1" |
0203b2e4 FS |
215 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
216 | ||
217 | # Disable the VG and check symlinks... | |
218 | lvm vgchange -an "$vgroup" | |
14f9c81f | 219 | udevadm wait --settle --timeout=30 --removed "/dev/$vgroup" "/dev/disk/by-label/mylvpart1" |
0203b2e4 FS |
220 | helper_check_device_symlinks "/dev/disk" |
221 | ||
222 | # reenable the VG and check the symlinks again if all LVs are properly activated | |
223 | lvm vgchange -ay "$vgroup" | |
14f9c81f | 224 | udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1" |
0203b2e4 FS |
225 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
226 | ||
227 | # Same as above, but now with more "stress" | |
dbc04797 | 228 | for i in {1..50}; do |
0203b2e4 FS |
229 | lvm vgchange -an "$vgroup" |
230 | lvm vgchange -ay "$vgroup" | |
231 | ||
dbc04797 | 232 | if ((i % 5 == 0)); then |
14f9c81f | 233 | udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1" |
0203b2e4 FS |
234 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
235 | fi | |
236 | done | |
237 | ||
238 | # Remove the first LV | |
239 | lvm lvremove -y "$vgroup/mypart1" | |
14f9c81f YW |
240 | udevadm wait --settle --timeout=30 --removed "/dev/$vgroup/mypart1" |
241 | udevadm wait --timeout=0 "/dev/$vgroup/mypart2" | |
0203b2e4 FS |
242 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
243 | ||
244 | # Create & remove LVs in a loop, i.e. with more "stress" | |
dbc04797 | 245 | for i in {1..16}; do |
0203b2e4 FS |
246 | # 1) Create 16 logical volumes |
247 | for part in {0..15}; do | |
248 | lvm lvcreate -y -L 4M "$vgroup" -n "looppart$part" | |
249 | done | |
250 | ||
251 | # 2) Immediately remove them | |
252 | lvm lvremove -y "$vgroup"/looppart{0..15} | |
253 | ||
dbc04797 | 254 | # 3) On every 4th iteration settle udev and check if all partitions are |
0203b2e4 | 255 | # indeed gone, and if all symlinks are still valid |
dbc04797 | 256 | if ((i % 4 == 0)); then |
0203b2e4 | 257 | for part in {0..15}; do |
14f9c81f | 258 | udevadm wait --settle --timeout=30 --removed "/dev/$vgroup/looppart$part" |
0203b2e4 FS |
259 | done |
260 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" | |
261 | fi | |
262 | done | |
263 | } | |
264 | ||
b1471e55 FS |
265 | testcase_btrfs_basic() { |
266 | local dev_stub i label mpoint uuid | |
267 | local devices=( | |
268 | /dev/disk/by-id/ata-foobar_deadbeefbtrfs{0..3} | |
269 | ) | |
270 | ||
271 | ls -l "${devices[@]}" | |
272 | ||
273 | echo "Single device: default settings" | |
274 | uuid="deadbeef-dead-dead-beef-000000000000" | |
275 | label="btrfs_root" | |
14f9c81f YW |
276 | udevadm lock --device="${devices[0]}" mkfs.btrfs -L "$label" -U "$uuid" "${devices[0]}" |
277 | udevadm wait --settle --timeout=30 "${devices[0]}" "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label" | |
b1471e55 | 278 | btrfs filesystem show |
b1471e55 FS |
279 | helper_check_device_symlinks |
280 | ||
281 | echo "Multiple devices: using partitions, data: single, metadata: raid1" | |
282 | uuid="deadbeef-dead-dead-beef-000000000001" | |
283 | label="btrfs_mpart" | |
bc6bd62c | 284 | udevadm lock --device="${devices[0]}" sfdisk --wipe=always "${devices[0]}" <<EOF |
b1471e55 FS |
285 | label: gpt |
286 | ||
287 | name="diskpart1", size=85M | |
288 | name="diskpart2", size=85M | |
289 | name="diskpart3", size=85M | |
290 | name="diskpart4", size=85M | |
291 | EOF | |
14f9c81f YW |
292 | udevadm wait --settle --timeout=30 /dev/disk/by-partlabel/diskpart{1..4} |
293 | udevadm lock --device="${devices[0]}" mkfs.btrfs -d single -m raid1 -L "$label" -U "$uuid" /dev/disk/by-partlabel/diskpart{1..4} | |
294 | udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label" | |
b1471e55 | 295 | btrfs filesystem show |
b1471e55 FS |
296 | helper_check_device_symlinks |
297 | wipefs -a -f "${devices[0]}" | |
14f9c81f | 298 | udevadm wait --settle --timeout=30 --removed /dev/disk/by-partlabel/diskpart{1..4} |
b1471e55 FS |
299 | |
300 | echo "Multiple devices: using disks, data: raid10, metadata: raid10, mixed mode" | |
301 | uuid="deadbeef-dead-dead-beef-000000000002" | |
302 | label="btrfs_mdisk" | |
14f9c81f YW |
303 | udevadm lock \ |
304 | --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs0 \ | |
305 | --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs1 \ | |
306 | --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs2 \ | |
307 | --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs3 \ | |
308 | mkfs.btrfs -M -d raid10 -m raid10 -L "$label" -U "$uuid" "${devices[@]}" | |
309 | udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label" | |
b1471e55 | 310 | btrfs filesystem show |
b1471e55 FS |
311 | helper_check_device_symlinks |
312 | ||
313 | echo "Multiple devices: using LUKS encrypted disks, data: raid1, metadata: raid1, mixed mode" | |
314 | uuid="deadbeef-dead-dead-beef-000000000003" | |
315 | label="btrfs_mencdisk" | |
316 | mpoint="/btrfs_enc$RANDOM" | |
317 | mkdir "$mpoint" | |
318 | # Create a key-file | |
319 | dd if=/dev/urandom of=/etc/btrfs_keyfile bs=64 count=1 iflag=fullblock | |
320 | chmod 0600 /etc/btrfs_keyfile | |
321 | # Encrypt each device and add it to /etc/crypttab, so it can be mounted | |
322 | # automagically later | |
323 | : >/etc/crypttab | |
324 | for ((i = 0; i < ${#devices[@]}; i++)); do | |
325 | # Intentionally use weaker cipher-related settings, since we don't care | |
326 | # about security here as it's a throwaway LUKS partition | |
327 | cryptsetup luksFormat -q \ | |
328 | --use-urandom --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \ | |
329 | --uuid "deadbeef-dead-dead-beef-11111111111$i" --label "encdisk$i" "${devices[$i]}" /etc/btrfs_keyfile | |
14f9c81f | 330 | udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-11111111111$i" "/dev/disk/by-label/encdisk$i" |
b1471e55 FS |
331 | # Add the device into /etc/crypttab, reload systemd, and then activate |
332 | # the device so we can create a filesystem on it later | |
333 | echo "encbtrfs$i UUID=deadbeef-dead-dead-beef-11111111111$i /etc/btrfs_keyfile luks,noearly" >>/etc/crypttab | |
334 | systemctl daemon-reload | |
335 | systemctl start "systemd-cryptsetup@encbtrfs$i" | |
336 | done | |
337 | helper_check_device_symlinks | |
338 | # Check if we have all necessary DM devices | |
339 | ls -l /dev/mapper/encbtrfs{0..3} | |
340 | # Create a multi-device btrfs filesystem on the LUKS devices | |
14f9c81f YW |
341 | udevadm lock \ |
342 | --device=/dev/mapper/encbtrfs0 \ | |
343 | --device=/dev/mapper/encbtrfs1 \ | |
344 | --device=/dev/mapper/encbtrfs2 \ | |
345 | --device=/dev/mapper/encbtrfs3 \ | |
346 | mkfs.btrfs -M -d raid1 -m raid1 -L "$label" -U "$uuid" /dev/mapper/encbtrfs{0..3} | |
347 | udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label" | |
b1471e55 | 348 | btrfs filesystem show |
b1471e55 FS |
349 | helper_check_device_symlinks |
350 | # Mount it and write some data to it we can compare later | |
351 | mount -t btrfs /dev/mapper/encbtrfs0 "$mpoint" | |
352 | echo "hello there" >"$mpoint/test" | |
353 | # "Deconstruct" the btrfs device and check if we're in a sane state (symlink-wise) | |
354 | umount "$mpoint" | |
355 | systemctl stop systemd-cryptsetup@encbtrfs{0..3} | |
14f9c81f | 356 | udevadm wait --settle --timeout=30 --removed "/dev/disk/by-uuid/$uuid" |
b1471e55 FS |
357 | helper_check_device_symlinks |
358 | # Add the mount point to /etc/fstab and check if the device can be put together | |
359 | # automagically. The source device is the DM name of the first LUKS device | |
360 | # (from /etc/crypttab). We have to specify all LUKS devices manually, as | |
361 | # registering the necessary devices is usually initrd's job (via btrfs device scan) | |
362 | dev_stub="/dev/mapper/encbtrfs" | |
363 | echo "/dev/mapper/encbtrfs0 $mpoint btrfs device=${dev_stub}0,device=${dev_stub}1,device=${dev_stub}2,device=${dev_stub}3 0 2" >>/etc/fstab | |
364 | # Tell systemd about the new mount | |
365 | systemctl daemon-reload | |
366 | # Restart cryptsetup.target to trigger autounlock of partitions in /etc/crypttab | |
367 | systemctl restart cryptsetup.target | |
368 | # Start the corresponding mount unit and check if the btrfs device was reconstructed | |
369 | # correctly | |
370 | systemctl start "${mpoint##*/}.mount" | |
14f9c81f | 371 | udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label" |
b1471e55 | 372 | btrfs filesystem show |
b1471e55 FS |
373 | helper_check_device_symlinks |
374 | grep "hello there" "$mpoint/test" | |
375 | # Cleanup | |
376 | systemctl stop "${mpoint##*/}.mount" | |
377 | systemctl stop systemd-cryptsetup@encbtrfs{0..3} | |
378 | sed -i "/${mpoint##*/}/d" /etc/fstab | |
379 | : >/etc/crypttab | |
380 | rm -fr "$mpoint" | |
381 | systemctl daemon-reload | |
382 | udevadm settle | |
383 | } | |
384 | ||
9cb41c33 FS |
385 | testcase_iscsi_lvm() { |
386 | local dev i label link lun_id mpoint target_name uuid | |
387 | local target_ip="127.0.0.1" | |
388 | local target_port="3260" | |
389 | local vgroup="iscsi_lvm$RANDOM" | |
390 | local expected_symlinks=() | |
391 | local devices=( | |
392 | /dev/disk/by-id/ata-foobar_deadbeefiscsi{0..3} | |
393 | ) | |
394 | ||
395 | ls -l "${devices[@]}" | |
396 | ||
397 | # Start the target daemon | |
398 | systemctl start tgtd | |
399 | systemctl status tgtd | |
400 | ||
401 | echo "iSCSI LUNs backed by devices" | |
402 | # See RFC3721 and RFC7143 | |
403 | target_name="iqn.2021-09.com.example:iscsi.test" | |
404 | # Initialize a new iSCSI target <$target_name> consisting of 4 LUNs, each | |
405 | # backed by a device | |
406 | tgtadm --lld iscsi --op new --mode target --tid=1 --targetname "$target_name" | |
407 | for ((i = 0; i < ${#devices[@]}; i++)); do | |
408 | # lun-0 is reserved by iSCSI | |
409 | lun_id="$((i + 1))" | |
410 | tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun "$lun_id" -b "${devices[$i]}" | |
411 | tgtadm --lld iscsi --op update --mode logicalunit --tid 1 --lun "$lun_id" | |
412 | expected_symlinks+=( | |
413 | "/dev/disk/by-path/ip-$target_ip:$target_port-iscsi-$target_name-lun-$lun_id" | |
414 | ) | |
415 | done | |
416 | tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL | |
417 | # Configure the iSCSI initiator | |
418 | iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover | |
419 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login | |
e529abe2 | 420 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
9cb41c33 FS |
421 | helper_check_device_symlinks |
422 | # Cleanup | |
423 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout | |
424 | tgtadm --lld iscsi --op delete --mode target --tid=1 | |
425 | ||
426 | echo "iSCSI LUNs backed by files + LVM" | |
427 | # Note: we use files here to "trick" LVM the disks are indeed on a different | |
428 | # host, so it doesn't automagically detect another path to the backing | |
429 | # device once we disconnect the iSCSI devices | |
430 | target_name="iqn.2021-09.com.example:iscsi.lvm.test" | |
431 | mpoint="$(mktemp -d /iscsi_storeXXX)" | |
432 | expected_symlinks=() | |
433 | # Use the first device as it's configured with larger capacity | |
434 | mkfs.ext4 -L iscsi_store "${devices[0]}" | |
14f9c81f | 435 | udevadm wait --settle --timeout=30 "${devices[0]}" |
9cb41c33 FS |
436 | mount "${devices[0]}" "$mpoint" |
437 | for i in {1..4}; do | |
438 | dd if=/dev/zero of="$mpoint/lun$i.img" bs=1M count=32 | |
439 | done | |
440 | # Initialize a new iSCSI target <$target_name> consisting of 4 LUNs, each | |
441 | # backed by a file | |
442 | tgtadm --lld iscsi --op new --mode target --tid=2 --targetname "$target_name" | |
443 | # lun-0 is reserved by iSCSI | |
444 | for i in {1..4}; do | |
445 | tgtadm --lld iscsi --op new --mode logicalunit --tid 2 --lun "$i" -b "$mpoint/lun$i.img" | |
446 | tgtadm --lld iscsi --op update --mode logicalunit --tid 2 --lun "$i" | |
447 | expected_symlinks+=( | |
448 | "/dev/disk/by-path/ip-$target_ip:$target_port-iscsi-$target_name-lun-$i" | |
449 | ) | |
450 | done | |
451 | tgtadm --lld iscsi --op bind --mode target --tid 2 -I ALL | |
452 | # Configure the iSCSI initiator | |
453 | iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover | |
454 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login | |
e529abe2 | 455 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
9cb41c33 FS |
456 | helper_check_device_symlinks |
457 | # Add all iSCSI devices into a LVM volume group, create two logical volumes, | |
458 | # and check if necessary symlinks exist (and are valid) | |
459 | lvm pvcreate -y "${expected_symlinks[@]}" | |
460 | lvm pvs | |
461 | lvm vgcreate "$vgroup" -y "${expected_symlinks[@]}" | |
462 | lvm vgs | |
463 | lvm vgchange -ay "$vgroup" | |
464 | lvm lvcreate -y -L 4M "$vgroup" -n mypart1 | |
465 | lvm lvcreate -y -L 8M "$vgroup" -n mypart2 | |
466 | lvm lvs | |
14f9c81f | 467 | udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" |
9cb41c33 | 468 | mkfs.ext4 -L mylvpart1 "/dev/$vgroup/mypart1" |
14f9c81f | 469 | udevadm wait --settle --timeout=30 "/dev/disk/by-label/mylvpart1" |
9cb41c33 FS |
470 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
471 | # Disconnect the iSCSI devices and check all the symlinks | |
472 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout | |
473 | # "Reset" the DM state, since we yanked the backing storage from under the LVM, | |
474 | # so the currently active VGs/LVs are invalid | |
475 | dmsetup remove_all --deferred | |
9cb41c33 | 476 | # The LVM and iSCSI related symlinks should be gone |
e529abe2 | 477 | udevadm wait --settle --timeout=30 --removed "/dev/$vgroup" "/dev/disk/by-label/mylvpart1" "${expected_symlinks[@]}" |
9cb41c33 FS |
478 | helper_check_device_symlinks "/dev/disk" |
479 | # Reconnect the iSCSI devices and check if everything get detected correctly | |
480 | iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover | |
481 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login | |
14f9c81f | 482 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1" |
9cb41c33 FS |
483 | helper_check_device_symlinks "/dev/disk" "/dev/$vgroup" |
484 | # Cleanup | |
485 | iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout | |
486 | tgtadm --lld iscsi --op delete --mode target --tid=2 | |
487 | umount "$mpoint" | |
488 | rm -rf "$mpoint" | |
489 | } | |
f415cdb3 FS |
490 | |
491 | testcase_long_sysfs_path() { | |
492 | local link logfile mpoint | |
493 | local expected_symlinks=( | |
494 | "/dev/disk/by-label/data_vol" | |
495 | "/dev/disk/by-label/swap_vol" | |
496 | "/dev/disk/by-partlabel/test_swap" | |
497 | "/dev/disk/by-partlabel/test_part" | |
498 | "/dev/disk/by-partuuid/deadbeef-dead-dead-beef-000000000000" | |
499 | "/dev/disk/by-uuid/deadbeef-dead-dead-beef-111111111111" | |
500 | "/dev/disk/by-uuid/deadbeef-dead-dead-beef-222222222222" | |
501 | ) | |
502 | ||
503 | # Make sure the test device is connected and show its "wonderful" path | |
504 | stat /sys/block/vda | |
505 | readlink -f /sys/block/vda/dev | |
506 | ||
14f9c81f | 507 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
f415cdb3 FS |
508 | |
509 | # Try to mount the data partition manually (using its label) | |
510 | mpoint="$(mktemp -d /logsysfsXXX)" | |
511 | mount LABEL=data_vol "$mpoint" | |
512 | touch "$mpoint/test" | |
513 | umount "$mpoint" | |
514 | # Do the same, but with UUID and using fstab | |
515 | echo "UUID=deadbeef-dead-dead-beef-222222222222 $mpoint ext4 defaults 0 0" >>/etc/fstab | |
516 | systemctl daemon-reload | |
517 | mount "$mpoint" | |
b26f4f00 | 518 | systemctl status "$mpoint" |
f415cdb3 FS |
519 | test -e "$mpoint/test" |
520 | umount "$mpoint" | |
521 | ||
522 | # Test out the swap partition | |
523 | swapon -v -L swap_vol | |
524 | swapoff -v -L swap_vol | |
525 | ||
7b3a1af0 FS |
526 | udevadm settle |
527 | ||
f415cdb3 | 528 | logfile="$(mktemp)" |
b26f4f00 | 529 | [[ "$(journalctl -b -q --no-pager -o short-monotonic -p info --grep "Device path.*vda.?' too long to fit into unit name" | wc -l)" -eq 0 ]] |
f415cdb3 | 530 | # Make sure we don't unnecessarily spam the log |
b26f4f00 | 531 | { journalctl -b -q --no-pager -o short-monotonic -p info --grep "/sys/devices/.+/vda[0-9]?" _PID=1 + UNIT=systemd-udevd.service || :;} | tee "$logfile" |
f415cdb3 FS |
532 | [[ "$(wc -l <"$logfile")" -lt 10 ]] |
533 | ||
534 | : >/etc/fstab | |
535 | rm -fr "${logfile:?}" "${mpoint:?}" | |
536 | } | |
537 | ||
3c9af05c | 538 | testcase_mdadm_basic() { |
18161cf0 | 539 | local i part_name raid_name raid_dev uuid |
3c9af05c FS |
540 | local expected_symlinks=() |
541 | local devices=( | |
542 | /dev/disk/by-id/ata-foobar_deadbeefmdadm{0..4} | |
543 | ) | |
544 | ||
545 | ls -l "${devices[@]}" | |
546 | ||
1bb38875 | 547 | echo "Mirror raid (RAID 1)" |
3c9af05c | 548 | raid_name="mdmirror" |
1bb38875 FS |
549 | raid_dev="/dev/md/$raid_name" |
550 | part_name="${raid_name}_part" | |
3c9af05c FS |
551 | uuid="aaaaaaaa:bbbbbbbb:cccccccc:00000001" |
552 | expected_symlinks=( | |
1bb38875 FS |
553 | "$raid_dev" |
554 | "/dev/disk/by-id/md-name-H:$raid_name" | |
3c9af05c | 555 | "/dev/disk/by-id/md-uuid-$uuid" |
1bb38875 | 556 | "/dev/disk/by-label/$part_name" # ext4 partition |
3c9af05c FS |
557 | ) |
558 | # Create a simple RAID 1 with an ext4 filesystem | |
1bb38875 FS |
559 | echo y | mdadm --create "$raid_dev" --name "$raid_name" --uuid "$uuid" /dev/disk/by-id/ata-foobar_deadbeefmdadm{0..1} -v -f --level=1 --raid-devices=2 |
560 | udevadm wait --settle --timeout=30 "$raid_dev" | |
561 | mkfs.ext4 -L "$part_name" "$raid_dev" | |
3c9af05c | 562 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
18161cf0 FS |
563 | for i in {0..9}; do |
564 | echo "Disassemble - reassemble loop, iteration #$i" | |
565 | mdadm -v --stop "$raid_dev" | |
566 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" | |
567 | mdadm --assemble "$raid_dev" --name "$raid_name" -v | |
568 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" | |
569 | done | |
1bb38875 FS |
570 | helper_check_device_symlinks |
571 | # Cleanup | |
572 | mdadm -v --stop "$raid_dev" | |
18161cf0 | 573 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" |
1bb38875 FS |
574 | |
575 | echo "Parity raid (RAID 5)" | |
576 | raid_name="mdparity" | |
577 | raid_dev="/dev/md/$raid_name" | |
578 | part_name="${raid_name}_part" | |
579 | uuid="aaaaaaaa:bbbbbbbb:cccccccc:00000101" | |
580 | expected_symlinks=( | |
581 | "$raid_dev" | |
582 | "/dev/disk/by-id/md-name-H:$raid_name" | |
583 | "/dev/disk/by-id/md-uuid-$uuid" | |
584 | "/dev/disk/by-label/$part_name" # ext4 partition | |
585 | ) | |
586 | # Create a simple RAID 5 with an ext4 filesystem | |
587 | echo y | mdadm --create "$raid_dev" --name "$raid_name" --uuid "$uuid" /dev/disk/by-id/ata-foobar_deadbeefmdadm{0..2} -v -f --level=5 --raid-devices=3 | |
588 | udevadm wait --settle --timeout=30 "$raid_dev" | |
589 | mkfs.ext4 -L "$part_name" "$raid_dev" | |
590 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" | |
18161cf0 FS |
591 | for i in {0..9}; do |
592 | echo "Disassemble - reassemble loop, iteration #$i" | |
593 | mdadm -v --stop "$raid_dev" | |
594 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" | |
595 | mdadm --assemble "$raid_dev" --name "$raid_name" -v | |
596 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" | |
597 | done | |
1bb38875 FS |
598 | helper_check_device_symlinks |
599 | # Cleanup | |
600 | mdadm -v --stop "$raid_dev" | |
18161cf0 | 601 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" |
1bb38875 | 602 | |
18161cf0 | 603 | echo "Mirror + parity raid (RAID 10) + multiple partitions" |
1bb38875 FS |
604 | raid_name="mdmirpar" |
605 | raid_dev="/dev/md/$raid_name" | |
606 | part_name="${raid_name}_part" | |
607 | uuid="aaaaaaaa:bbbbbbbb:cccccccc:00001010" | |
608 | expected_symlinks=( | |
609 | "$raid_dev" | |
610 | "/dev/disk/by-id/md-name-H:$raid_name" | |
611 | "/dev/disk/by-id/md-uuid-$uuid" | |
612 | "/dev/disk/by-label/$part_name" # ext4 partition | |
18161cf0 FS |
613 | # Partitions |
614 | "${raid_dev}1" | |
615 | "${raid_dev}2" | |
616 | "${raid_dev}3" | |
617 | "/dev/disk/by-id/md-name-H:$raid_name-part1" | |
618 | "/dev/disk/by-id/md-name-H:$raid_name-part2" | |
619 | "/dev/disk/by-id/md-name-H:$raid_name-part3" | |
620 | "/dev/disk/by-id/md-uuid-$uuid-part1" | |
621 | "/dev/disk/by-id/md-uuid-$uuid-part2" | |
622 | "/dev/disk/by-id/md-uuid-$uuid-part3" | |
1bb38875 FS |
623 | ) |
624 | # Create a simple RAID 10 with an ext4 filesystem | |
625 | echo y | mdadm --create "$raid_dev" --name "$raid_name" --uuid "$uuid" /dev/disk/by-id/ata-foobar_deadbeefmdadm{0..3} -v -f --level=10 --raid-devices=4 | |
626 | udevadm wait --settle --timeout=30 "$raid_dev" | |
18161cf0 FS |
627 | # Partition the raid device |
628 | # Here, 'udevadm lock' is meaningless, as udevd does not lock MD devices. | |
629 | sfdisk --wipe=always "$raid_dev" <<EOF | |
630 | label: gpt | |
631 | ||
632 | uuid="deadbeef-dead-dead-beef-111111111111", name="mdpart1", size=8M | |
633 | uuid="deadbeef-dead-dead-beef-222222222222", name="mdpart2", size=32M | |
634 | uuid="deadbeef-dead-dead-beef-333333333333", name="mdpart3", size=16M | |
635 | EOF | |
636 | udevadm wait --settle --timeout=30 "/dev/disk/by-id/md-uuid-$uuid-part2" | |
637 | mkfs.ext4 -L "$part_name" "/dev/disk/by-id/md-uuid-$uuid-part2" | |
d3ce9bed | 638 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
18161cf0 FS |
639 | for i in {0..9}; do |
640 | echo "Disassemble - reassemble loop, iteration #$i" | |
641 | mdadm -v --stop "$raid_dev" | |
642 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" | |
643 | mdadm --assemble "$raid_dev" --name "$raid_name" -v | |
644 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" | |
645 | done | |
d3ce9bed | 646 | helper_check_device_symlinks |
18161cf0 FS |
647 | # Cleanup |
648 | mdadm -v --stop "$raid_dev" | |
649 | # Check if all expected symlinks were removed after the cleanup | |
650 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" | |
d3ce9bed FS |
651 | } |
652 | ||
653 | testcase_mdadm_lvm() { | |
654 | local part_name raid_name raid_dev uuid vgroup | |
655 | local expected_symlinks=() | |
656 | local devices=( | |
657 | /dev/disk/by-id/ata-foobar_deadbeefmdadmlvm{0..4} | |
658 | ) | |
659 | ||
660 | ls -l "${devices[@]}" | |
661 | ||
662 | raid_name="mdlvm" | |
663 | raid_dev="/dev/md/$raid_name" | |
664 | part_name="${raid_name}_part" | |
665 | vgroup="${raid_name}_vg" | |
666 | uuid="aaaaaaaa:bbbbbbbb:ffffffff:00001010" | |
667 | expected_symlinks=( | |
668 | "$raid_dev" | |
669 | "/dev/$vgroup/mypart1" # LVM partition | |
670 | "/dev/$vgroup/mypart2" # LVM partition | |
671 | "/dev/disk/by-id/md-name-H:$raid_name" | |
672 | "/dev/disk/by-id/md-uuid-$uuid" | |
673 | "/dev/disk/by-label/$part_name" # ext4 partition | |
674 | ) | |
675 | # Create a RAID 10 with LVM + ext4 | |
676 | echo y | mdadm --create "$raid_dev" --name "$raid_name" --uuid "$uuid" /dev/disk/by-id/ata-foobar_deadbeefmdadmlvm{0..3} -v -f --level=10 --raid-devices=4 | |
677 | udevadm wait --settle --timeout=30 "$raid_dev" | |
678 | # Create an LVM on the MD | |
679 | lvm pvcreate -y "$raid_dev" | |
680 | lvm pvs | |
681 | lvm vgcreate "$vgroup" -y "$raid_dev" | |
682 | lvm vgs | |
683 | lvm vgchange -ay "$vgroup" | |
684 | lvm lvcreate -y -L 4M "$vgroup" -n mypart1 | |
685 | lvm lvcreate -y -L 8M "$vgroup" -n mypart2 | |
686 | lvm lvs | |
687 | udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" | |
688 | mkfs.ext4 -L "$part_name" "/dev/$vgroup/mypart2" | |
689 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" | |
690 | # Disassemble the array | |
691 | lvm vgchange -an "$vgroup" | |
692 | mdadm -v --stop "$raid_dev" | |
6d49e094 | 693 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" |
d3ce9bed FS |
694 | helper_check_device_symlinks |
695 | # Reassemble it and check if all required symlinks exist | |
1bb38875 | 696 | mdadm --assemble "$raid_dev" --name "$raid_name" -v |
3c9af05c FS |
697 | udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" |
698 | helper_check_device_symlinks | |
6d49e094 FS |
699 | # Cleanup |
700 | lvm vgchange -an "$vgroup" | |
701 | mdadm -v --stop "$raid_dev" | |
702 | # Check if all expected symlinks were removed after the cleanup | |
703 | udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}" | |
3c9af05c FS |
704 | } |
705 | ||
f2204ac2 FS |
706 | : >/failed |
707 | ||
708 | udevadm settle | |
8a088877 | 709 | udevadm control --log-level debug |
f2204ac2 FS |
710 | lsblk -a |
711 | ||
d430e451 FS |
712 | echo "Check if all symlinks under /dev/disk/ are valid (pre-test)" |
713 | helper_check_device_symlinks | |
714 | ||
f2204ac2 FS |
715 | # TEST_FUNCTION_NAME is passed on the kernel command line via systemd.setenv= |
716 | # in the respective test.sh file | |
717 | if ! command -v "${TEST_FUNCTION_NAME:?}"; then | |
718 | echo >&2 "Missing verification handler for test case '$TEST_FUNCTION_NAME'" | |
719 | exit 1 | |
720 | fi | |
721 | ||
722 | echo "TEST_FUNCTION_NAME=$TEST_FUNCTION_NAME" | |
723 | "$TEST_FUNCTION_NAME" | |
f415cdb3 | 724 | udevadm settle |
f2204ac2 | 725 | |
d430e451 FS |
726 | echo "Check if all symlinks under /dev/disk/ are valid (post-test)" |
727 | helper_check_device_symlinks | |
728 | ||
8a088877 YW |
729 | udevadm control --log-level info |
730 | ||
f2204ac2 FS |
731 | systemctl status systemd-udevd |
732 | ||
733 | touch /testok | |
734 | rm /failed |