]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/units/testsuite-64.sh
test: add coverage for #24177
[thirdparty/systemd.git] / test / units / testsuite-64.sh
CommitLineData
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
5set -eux
6set -o pipefail
7
d430e451 8# Check if all symlinks under /dev/disk/ are valid
df72bd45 9# shellcheck disable=SC2120
de11005c
FS
10helper_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")"
27 # Both checks should do virtually the same thing, but check both to be
28 # on the safe side
29 if [[ ! -e "$link" || ! -e "$target" ]]; then
30 echo >&2 "ERROR: symlink '$link' points to '$target' which doesn't exist"
31 return 1
32 fi
33
34 # Check if the symlink points to the correct device in /dev
35 dev="/dev/$(udevadm info -q name "$link")"
36 if [[ "$target" != "$dev" ]]; then
37 echo >&2 "ERROR: symlink '$link' points to '$target' but '$dev' was expected"
38 return 1
39 fi
df72bd45 40 done < <(find "${paths[@]}" -type l)
de11005c 41)}
d430e451 42
ee275012
YW
43helper_check_udev_watch() {(
44 set +x
45
46 local link target id dev
47
48 while read -r link; do
49 target="$(readlink "$link")"
ee275012
YW
50 if [[ ! -L "/run/udev/watch/$target" ]]; then
51 echo >&2 "ERROR: symlink /run/udev/watch/$target does not exist"
52 return 1
53 fi
54 if [[ "$(readlink "/run/udev/watch/$target")" != "$(basename "$link")" ]]; then
55 echo >&2 "ERROR: symlink target of /run/udev/watch/$target is inconsistent with $link"
56 return 1
57 fi
58
59 if [[ "$target" =~ ^[0-9]+$ ]]; then
60 # $link is ID -> wd
61 id="$(basename "$link")"
62 else
63 # $link is wd -> ID
64 id="$target"
65 fi
66
67 if [[ "${id:0:1}" == "b" ]]; then
68 dev="/dev/block/${id:1}"
69 elif [[ "${id:0:1}" == "c" ]]; then
70 dev="/dev/char/${id:1}"
71 else
72 echo >&2 "ERROR: unexpected device ID '$id'"
73 return 1
74 fi
75
76 if [[ ! -e "$dev" ]]; then
77 echo >&2 "ERROR: device '$dev' corresponding to symlink '$link' does not exist"
78 return 1
79 fi
80 done < <(find /run/udev/watch -type l)
81)}
82
9c126b2c
YW
83check_device_unit() {(
84 set +x
85
86 local log_level link links path syspath unit
87
88 log_level="${1?}"
89 path="${2?}"
90 unit=$(systemd-escape --path --suffix=device "$path")
91
5479d0f8
YW
92 [[ "$log_level" == 1 ]] && echo "INFO: check_device_unit($unit)"
93
9c126b2c
YW
94 syspath=$(systemctl show --value --property SysFSPath "$unit" 2>/dev/null)
95 if [[ -z "$syspath" ]]; then
96 [[ "$log_level" == 1 ]] && echo >&2 "ERROR: $unit not found."
97 return 1
98 fi
99
100 if [[ ! -L "$path" ]]; then
101 if [[ ! -d "$syspath" ]]; then
102 [[ "$log_level" == 1 ]] && echo >&2 "ERROR: $unit exists for $syspath but it does not exist."
103 return 1
104 fi
105 return 0
106 fi
107
108 if [[ ! -b "$path" && ! -c "$path" ]]; then
109 [[ "$log_level" == 1 ]] && echo >&2 "ERROR: invalid file type $path"
110 return 1
111 fi
112
113 read -r -a links < <(udevadm info -q symlink "$syspath" 2>/dev/null)
114 for link in "${links[@]}"; do
115 if [[ "/dev/$link" == "$path" ]]; then # DEVLINKS= given by -q symlink are relative to /dev
116 return 0
117 fi
118 done
119
120 read -r -a links < <(udevadm info "$syspath" | sed -ne '/SYSTEMD_ALIAS=/ { s/^E: SYSTEMD_ALIAS=//; p }' 2>/dev/null)
121 for link in "${links[@]}"; do
122 if [[ "$link" == "$path" ]]; then # SYSTEMD_ALIAS= are absolute
123 return 0
124 fi
125 done
126
127 [[ "$log_level" == 1 ]] && echo >&2 "ERROR: $unit exists for $syspath but it does not have the corresponding DEVLINKS or SYSTEMD_ALIAS."
128 return 1
129)}
130
131check_device_units() {(
132 set +x
133
134 local log_level path paths
135
136 log_level="${1?}"
137 shift
138 paths=("$@")
139
140 for path in "${paths[@]}"; do
141 if ! check_device_unit "$log_level" "$path"; then
142 return 1
143 fi
144 done
145
146 while read -r unit _; do
147 path=$(systemd-escape --path --unescape "$unit")
148 if ! check_device_unit "$log_level" "$path"; then
149 return 1
150 fi
d6ef4ebb 151 done < <(systemctl list-units --all --type=device --no-legend dev-* | awk '$1 !~ /dev-tty.+/ { print $1 }' | sed -e 's/\.device$//')
9c126b2c
YW
152
153 return 0
154)}
155
156helper_check_device_units() {(
157 set +x
158
159 local i
160
5479d0f8 161 for (( i = 0; i < 20; i++ )); do
9c126b2c
YW
162 if check_device_units 0 "$@"; then
163 return 0
164 fi
5479d0f8 165 sleep .5
9c126b2c
YW
166 done
167
168 check_device_units 1 "$@"
169)}
170
f2204ac2
FS
171testcase_megasas2_basic() {
172 lsblk -S
173 [[ "$(lsblk --scsi --noheadings | wc -l)" -ge 128 ]]
174}
175
176testcase_nvme_basic() {
177 lsblk --noheadings | grep "^nvme"
178 [[ "$(lsblk --noheadings | grep -c "^nvme")" -ge 28 ]]
179}
180
6788418a
FS
181testcase_nvme_subsystem() {
182 local expected_symlinks=(
183 # Controller(s)
184 /dev/disk/by-id/nvme-QEMU_NVMe_Ctrl_deadbeef
185 # Shared namespaces
186 /dev/disk/by-path/pci-*-nvme-16
187 /dev/disk/by-path/pci-*-nvme-17
188 )
189
190 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
191}
192
f2204ac2 193testcase_virtio_scsi_identically_named_partitions() {
0bfe2aa3
YW
194 local num
195
1f9caf28 196 if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
0bfe2aa3
YW
197 num=$((4 * 4))
198 else
199 num=$((16 * 8))
200 fi
201
f2204ac2 202 lsblk --noheadings -a -o NAME,PARTLABEL
0bfe2aa3 203 [[ "$(lsblk --noheadings -a -o NAME,PARTLABEL | grep -c "Hello world")" -eq "$num" ]]
f2204ac2
FS
204}
205
d0cbad16
FS
206testcase_multipath_basic_failover() {
207 local dmpath i path wwid
208
209 # Configure multipath
210 cat >/etc/multipath.conf <<\EOF
211defaults {
212 # Use /dev/mapper/$WWN paths instead of /dev/mapper/mpathX
213 user_friendly_names no
214 find_multipaths yes
215 enable_foreign "^$"
216}
217
218blacklist_exceptions {
219 property "(SCSI_IDENT_|ID_WWN)"
220}
221
222blacklist {
223}
224EOF
225 modprobe -v dm_multipath
226 systemctl start multipathd.service
227 systemctl status multipathd.service
228 multipath -ll
cd37793d 229 udevadm settle
d0cbad16
FS
230 ls -l /dev/disk/by-id/
231
1678bd2f 232 for i in {0..15}; do
d0cbad16
FS
233 wwid="deaddeadbeef$(printf "%.4d" "$i")"
234 path="/dev/disk/by-id/wwn-0x$wwid"
235 dmpath="$(readlink -f "$path")"
236
237 lsblk "$path"
238 multipath -C "$dmpath"
239 # We should have 4 active paths for each multipath device
240 [[ "$(multipath -l "$path" | grep -c running)" -eq 4 ]]
241 done
242
243 # Test failover (with the first multipath device that has a partitioned disk)
244 echo "${FUNCNAME[0]}: test failover"
245 local device expected link mpoint part
246 local -a devices
84e5b922 247 mkdir -p /mnt
d0cbad16
FS
248 mpoint="$(mktemp -d /mnt/mpathXXX)"
249 wwid="deaddeadbeef0000"
250 path="/dev/disk/by-id/wwn-0x$wwid"
251
252 # All following symlinks should exists and should be valid
253 local -a part_links=(
254 "/dev/disk/by-id/wwn-0x$wwid-part2"
255 "/dev/disk/by-partlabel/failover_part"
256 "/dev/disk/by-partuuid/deadbeef-dead-dead-beef-000000000000"
257 "/dev/disk/by-label/failover_vol"
258 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-111111111111"
259 )
14f9c81f 260 udevadm wait --settle --timeout=30 "${part_links[@]}"
9c126b2c 261 helper_check_device_units "${part_links[@]}"
d0cbad16
FS
262
263 # Choose a random symlink to the failover data partition each time, for
264 # a better coverage
265 part="${part_links[$RANDOM % ${#part_links[@]}]}"
266
267 # Get all devices attached to a specific multipath device (in H:C:T:L format)
268 # and sort them in a random order, so we cut off different paths each time
269 mapfile -t devices < <(multipath -l "$path" | grep -Eo '[0-9]+:[0-9]+:[0-9]+:[0-9]+' | sort -R)
270 if [[ "${#devices[@]}" -ne 4 ]]; then
271 echo "Expected 4 devices attached to WWID=$wwid, got ${#devices[@]} instead"
272 return 1
273 fi
274 # Drop the last path from the array, since we want to leave at least one path active
275 unset "devices[3]"
276 # Mount the first multipath partition, write some data we can check later,
277 # and then disconnect the remaining paths one by one while checking if we
278 # can still read/write from the mount
279 mount -t ext4 "$part" "$mpoint"
280 expected=0
281 echo -n "$expected" >"$mpoint/test"
282 # Sanity check we actually wrote what we wanted
283 [[ "$(<"$mpoint/test")" == "$expected" ]]
284
285 for device in "${devices[@]}"; do
286 echo offline >"/sys/class/scsi_device/$device/device/state"
287 [[ "$(<"$mpoint/test")" == "$expected" ]]
288 expected="$((expected + 1))"
289 echo -n "$expected" >"$mpoint/test"
290
291 # Make sure all symlinks are still valid
14f9c81f 292 udevadm wait --settle --timeout=30 "${part_links[@]}"
9c126b2c 293 helper_check_device_units "${part_links[@]}"
d0cbad16
FS
294 done
295
296 multipath -l "$path"
297 # Three paths should be now marked as 'offline' and one as 'running'
298 [[ "$(multipath -l "$path" | grep -c offline)" -eq 3 ]]
299 [[ "$(multipath -l "$path" | grep -c running)" -eq 1 ]]
300
301 umount "$mpoint"
302 rm -fr "$mpoint"
303}
304
a2e41b81 305testcase_simultaneous_events_1() {
ad8c442a 306 local disk expected i iterations key link num_part part partscript rule target timeout
d64b44be 307 local -a devices symlinks
ad8c442a 308 local -A running
35497c7c 309
1f9caf28 310 if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
d64b44be 311 num_part=2
a1bed4e4
YW
312 iterations=10
313 timeout=240
314 else
d64b44be 315 num_part=10
a1bed4e4
YW
316 iterations=100
317 timeout=30
318 fi
319
d64b44be
YW
320 for disk in {0..9}; do
321 link="/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_deadbeeftest${disk}"
322 target="$(readlink -f "$link")"
323 if [[ ! -b "$target" ]]; then
324 echo "ERROR: failed to find the test SCSI block device $link"
325 return 1
326 fi
327
328 devices+=("$target")
329 done
330
331 for ((part = 1; part <= num_part; part++)); do
332 symlinks+=(
333 "/dev/disk/by-partlabel/test${part}"
334 )
335 done
336
337 partscript="$(mktemp)"
338
35497c7c 339 cat >"$partscript" <<EOF
d64b44be
YW
340$(for ((part = 1; part <= num_part; part++)); do printf 'name="test%d", size=2M\n' "$part"; done)
341EOF
342
343 rule=/run/udev/rules.d/50-test.rules
344 mkdir -p "${rule%/*}"
345 cat >"$rule" <<EOF
346SUBSYSTEM=="block", KERNEL=="${devices[4]##*/}*|${devices[5]##*/}*", OPTIONS="link_priority=10"
35497c7c
FS
347EOF
348
d64b44be 349 udevadm control --reload
35497c7c 350
ba669952 351 # Delete the partitions, immediately recreate them, wait for udev to settle
35497c7c
FS
352 # down, and then check if we have any dangling symlinks in /dev/disk/. Rinse
353 # and repeat.
354 #
355 # On unpatched udev versions the delete-recreate cycle may trigger a race
356 # leading to dead symlinks in /dev/disk/
1e429729 357 for ((i = 1; i <= iterations; i++)); do
d64b44be
YW
358 for disk in {0..9}; do
359 if ((disk % 2 == i % 2)); then
360 udevadm lock --device="${devices[$disk]}" sfdisk -q --delete "${devices[$disk]}" &
361 else
362 udevadm lock --device="${devices[$disk]}" sfdisk -q -X gpt "${devices[$disk]}" <"$partscript" &
363 fi
ad8c442a 364 running[$disk]=$!
d64b44be
YW
365 done
366
ad8c442a
YW
367 for key in "${!running[@]}"; do
368 wait "${running[$key]}"
369 unset "running[$key]"
d64b44be
YW
370 done
371
372 if ((i % 10 <= 1)); then
373 udevadm wait --settle --timeout="$timeout" "${devices[@]}" "${symlinks[@]}"
35497c7c 374 helper_check_device_symlinks
ee275012 375 helper_check_udev_watch
d64b44be
YW
376 for ((part = 1; part <= num_part; part++)); do
377 link="/dev/disk/by-partlabel/test${part}"
378 target="$(readlink -f "$link")"
379 if ((i % 2 == 0)); then
380 expected="${devices[5]}$part"
381 else
382 expected="${devices[4]}$part"
383 fi
384 if [[ "$target" != "$expected" ]]; then
385 echo >&2 "ERROR: symlink '/dev/disk/by-partlabel/test${part}' points to '$target' but '$expected' was expected"
386 return 1
387 fi
388 done
35497c7c
FS
389 fi
390 done
391
9c126b2c 392 helper_check_device_units
d64b44be
YW
393 rm -f "$rule" "$partscript"
394
395 udevadm control --reload
35497c7c
FS
396}
397
a2e41b81
YW
398testcase_simultaneous_events_2() {
399 local disk expected i iterations key link num_part part partscript target timeout
400 local -a devices symlinks
401 local -A running
402
403 if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
404 num_part=20
405 iterations=1
406 timeout=2400
407 else
408 num_part=100
409 iterations=3
410 timeout=300
411 fi
412
413 for disk in {0..9}; do
414 link="/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_deadbeeftest${disk}"
415 target="$(readlink -f "$link")"
416 if [[ ! -b "$target" ]]; then
417 echo "ERROR: failed to find the test SCSI block device $link"
418 return 1
419 fi
420
421 devices+=("$target")
422 done
423
424 symlinks=("/dev/disk/by-partlabel/testlabel")
425
426 partscript="$(mktemp)"
427
428 cat >"$partscript" <<EOF
429$(for ((part = 1; part <= num_part; part++)); do printf 'name="testlabel", size=1M\n'; done)
430EOF
431
432 echo "## $iterations iterations start: $(date '+%H:%M:%S.%N')"
433 for ((i = 1; i <= iterations; i++)); do
434
435 for disk in {0..9}; do
436 udevadm lock --device="${devices[$disk]}" sfdisk -q --delete "${devices[$disk]}" &
437 running[$disk]=$!
438 done
439
440 for key in "${!running[@]}"; do
441 wait "${running[$key]}"
442 unset "running[$key]"
443 done
444
445 for disk in {0..9}; do
446 udevadm lock --device="${devices[$disk]}" sfdisk -q -X gpt "${devices[$disk]}" <"$partscript" &
447 running[$disk]=$!
448 done
449
450 for key in "${!running[@]}"; do
451 wait "${running[$key]}"
452 unset "running[$key]"
453 done
454
455 udevadm wait --settle --timeout="$timeout" "${devices[@]}" "${symlinks[@]}"
456 done
457 echo "## $iterations iterations end: $(date '+%H:%M:%S.%N')"
458}
459
460testcase_simultaneous_events() {
461 testcase_simultaneous_events_1
462 testcase_simultaneous_events_2
463}
464
0203b2e4 465testcase_lvm_basic() {
998fb5c5 466 local i iterations partitions part timeout
0203b2e4
FS
467 local vgroup="MyTestGroup$RANDOM"
468 local devices=(
469 /dev/disk/by-id/ata-foobar_deadbeeflvm{0..3}
470 )
471
1f9caf28 472 if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
dd2b99ee
FS
473 timeout=180
474 else
475 timeout=30
476 fi
0203b2e4
FS
477 # Make sure all the necessary soon-to-be-LVM devices exist
478 ls -l "${devices[@]}"
479
480 # Add all test devices into a volume group, create two logical volumes,
481 # and check if necessary symlinks exist (and are valid)
482 lvm pvcreate -y "${devices[@]}"
483 lvm pvs
484 lvm vgcreate "$vgroup" -y "${devices[@]}"
485 lvm vgs
486 lvm vgchange -ay "$vgroup"
487 lvm lvcreate -y -L 4M "$vgroup" -n mypart1
6299b6e5 488 lvm lvcreate -y -L 32M "$vgroup" -n mypart2
0203b2e4 489 lvm lvs
1e429729 490 udevadm wait --settle --timeout="$timeout" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2"
0203b2e4 491 mkfs.ext4 -L mylvpart1 "/dev/$vgroup/mypart1"
1e429729 492 udevadm wait --settle --timeout="$timeout" "/dev/disk/by-label/mylvpart1"
0203b2e4 493 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 494 helper_check_device_units
0203b2e4 495
d60e3482
YW
496 # Mount mypart1 through by-label devlink
497 mkdir -p /tmp/mypart1-mount-point
498 mount /dev/disk/by-label/mylvpart1 /tmp/mypart1-mount-point
499 timeout 30 bash -c "while ! systemctl -q is-active /tmp/mypart1-mount-point; do sleep .2; done"
500 # Extend the partition and check if the device and mount units are still active.
501 # See https://bugzilla.redhat.com/show_bug.cgi?id=2158628
502 # Note, the test below may be unstable with LVM2 without the following patch:
503 # https://github.com/lvmteam/lvm2/pull/105
504 # But, to reproduce the issue, udevd must start to process the first 'change' uevent
505 # earlier than extending the volume has been finished, and in most case, the extension
506 # is hopefully fast.
507 lvm lvextend -y --size 8M "/dev/$vgroup/mypart1"
508 udevadm wait --settle --timeout="$timeout" "/dev/disk/by-label/mylvpart1"
509 timeout 30 bash -c "while ! systemctl -q is-active '/dev/$vgroup/mypart1'; do sleep .2; done"
510 timeout 30 bash -c "while ! systemctl -q is-active /tmp/mypart1-mount-point; do sleep .2; done"
511 # Umount the partition, otherwise the underlying device unit will stay in
512 # the inactive state and not be collected, and helper_check_device_units() will fail.
513 systemctl show /tmp/mypart1-mount-point
514 umount /tmp/mypart1-mount-point
515
ede0fe02
YW
516 # Rename partitions (see issue #24518)
517 lvm lvrename "/dev/$vgroup/mypart1" renamed1
518 lvm lvrename "/dev/$vgroup/mypart2" renamed2
519 udevadm wait --settle --timeout="$timeout" --removed "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2"
520 udevadm wait --settle --timeout="$timeout" "/dev/$vgroup/renamed1" "/dev/$vgroup/renamed2"
521 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
522 helper_check_device_units
523
524 # Rename them back
525 lvm lvrename "/dev/$vgroup/renamed1" mypart1
526 lvm lvrename "/dev/$vgroup/renamed2" mypart2
527 udevadm wait --settle --timeout="$timeout" --removed "/dev/$vgroup/renamed1" "/dev/$vgroup/renamed2"
528 udevadm wait --settle --timeout="$timeout" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2"
529 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
530 helper_check_device_units
531
6299b6e5
FS
532 # Do not "unready" suspended encrypted devices w/o superblock info
533 # See:
534 # - https://github.com/systemd/systemd/pull/24177
535 # - https://bugzilla.redhat.com/show_bug.cgi?id=1985288
536 dd if=/dev/urandom of=/etc/lvm_keyfile bs=64 count=1 iflag=fullblock
537 chmod 0600 /etc/lvm_keyfile
538 # Intentionally use weaker cipher-related settings, since we don't care
539 # about security here as it's a throwaway LUKS partition
540 cryptsetup luksFormat -q --use-urandom --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \
541 "/dev/$vgroup/mypart2" /etc/lvm_keyfile
542 # Mount the LUKS partition & create a filesystem on it
543 mkdir -p /tmp/lvmluksmnt
544 cryptsetup open --key-file=/etc/lvm_keyfile "/dev/$vgroup/mypart2" "lvmluksmap"
545 udevadm wait --settle --timeout="$timeout" "/dev/mapper/lvmluksmap"
546 mkfs.ext4 -L lvmluksfs "/dev/mapper/lvmluksmap"
547 udevadm wait --settle --timeout="$timeout" "/dev/disk/by-label/lvmluksfs"
548 # Make systemd "interested" in the mount by adding it to /etc/fstab
549 echo "/dev/disk/by-label/lvmluksfs /tmp/lvmluksmnt ext4 defaults 0 2" >>/etc/fstab
550 systemctl daemon-reload
551 mount "/tmp/lvmluksmnt"
552 mountpoint "/tmp/lvmluksmnt"
553 # Temporarily suspend the LUKS device and trigger udev - basically what `cryptsetup resize`
554 # does but in a more deterministic way suitable for a test/reproducer
555 for _ in {0..5}; do
556 dmsetup suspend "/dev/mapper/lvmluksmap"
557 udevadm trigger -v --settle "/dev/mapper/lvmluksmap"
558 dmsetup resume "/dev/mapper/lvmluksmap"
559 # The mount should survive this sequence of events
560 mountpoint "/tmp/lvmluksmnt"
561 done
562 # Cleanup
563 umount "/tmp/lvmluksmnt"
564 cryptsetup close "/dev/mapper/lvmluksmap"
565 sed -i "/lvmluksfs/d" "/etc/fstab"
566 systemctl daemon-reload
567
0203b2e4
FS
568 # Disable the VG and check symlinks...
569 lvm vgchange -an "$vgroup"
1e429729 570 udevadm wait --settle --timeout="$timeout" --removed "/dev/$vgroup" "/dev/disk/by-label/mylvpart1"
0203b2e4 571 helper_check_device_symlinks "/dev/disk"
9c126b2c 572 helper_check_device_units
0203b2e4
FS
573
574 # reenable the VG and check the symlinks again if all LVs are properly activated
575 lvm vgchange -ay "$vgroup"
1e429729 576 udevadm wait --settle --timeout="$timeout" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1"
0203b2e4 577 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 578 helper_check_device_units
0203b2e4
FS
579
580 # Same as above, but now with more "stress"
1f9caf28 581 if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
dd2b99ee
FS
582 iterations=10
583 else
584 iterations=50
585 fi
586
1e429729 587 for ((i = 1; i <= iterations; i++)); do
0203b2e4
FS
588 lvm vgchange -an "$vgroup"
589 lvm vgchange -ay "$vgroup"
590
dbc04797 591 if ((i % 5 == 0)); then
1e429729 592 udevadm wait --settle --timeout="$timeout" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1"
0203b2e4 593 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 594 helper_check_device_units
0203b2e4
FS
595 fi
596 done
597
598 # Remove the first LV
599 lvm lvremove -y "$vgroup/mypart1"
1e429729 600 udevadm wait --settle --timeout="$timeout" --removed "/dev/$vgroup/mypart1"
14f9c81f 601 udevadm wait --timeout=0 "/dev/$vgroup/mypart2"
0203b2e4 602 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 603 helper_check_device_units
0203b2e4
FS
604
605 # Create & remove LVs in a loop, i.e. with more "stress"
1f9caf28 606 if [[ -v ASAN_OPTIONS ]]; then
998fb5c5 607 iterations=8
07faa499 608 partitions=16
998fb5c5 609 elif [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then
dd2b99ee 610 iterations=8
998fb5c5 611 partitions=8
dd2b99ee
FS
612 else
613 iterations=16
998fb5c5 614 partitions=16
dd2b99ee
FS
615 fi
616
1e429729 617 for ((i = 1; i <= iterations; i++)); do
998fb5c5
FS
618 # 1) Create some logical volumes
619 for ((part = 0; part < partitions; part++)); do
0203b2e4
FS
620 lvm lvcreate -y -L 4M "$vgroup" -n "looppart$part"
621 done
622
623 # 2) Immediately remove them
998fb5c5 624 lvm lvremove -y $(seq -f "$vgroup/looppart%g" 0 "$((partitions - 1))")
0203b2e4 625
dbc04797 626 # 3) On every 4th iteration settle udev and check if all partitions are
0203b2e4 627 # indeed gone, and if all symlinks are still valid
dbc04797 628 if ((i % 4 == 0)); then
998fb5c5 629 for ((part = 0; part < partitions; part++)); do
1e429729 630 udevadm wait --settle --timeout="$timeout" --removed "/dev/$vgroup/looppart$part"
0203b2e4
FS
631 done
632 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 633 helper_check_device_units
0203b2e4
FS
634 fi
635 done
636}
637
b1471e55
FS
638testcase_btrfs_basic() {
639 local dev_stub i label mpoint uuid
640 local devices=(
641 /dev/disk/by-id/ata-foobar_deadbeefbtrfs{0..3}
642 )
643
644 ls -l "${devices[@]}"
645
646 echo "Single device: default settings"
647 uuid="deadbeef-dead-dead-beef-000000000000"
648 label="btrfs_root"
14f9c81f
YW
649 udevadm lock --device="${devices[0]}" mkfs.btrfs -L "$label" -U "$uuid" "${devices[0]}"
650 udevadm wait --settle --timeout=30 "${devices[0]}" "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label"
b1471e55 651 btrfs filesystem show
b1471e55 652 helper_check_device_symlinks
9c126b2c 653 helper_check_device_units
b1471e55
FS
654
655 echo "Multiple devices: using partitions, data: single, metadata: raid1"
656 uuid="deadbeef-dead-dead-beef-000000000001"
657 label="btrfs_mpart"
bc6bd62c 658 udevadm lock --device="${devices[0]}" sfdisk --wipe=always "${devices[0]}" <<EOF
b1471e55
FS
659label: gpt
660
661name="diskpart1", size=85M
662name="diskpart2", size=85M
663name="diskpart3", size=85M
664name="diskpart4", size=85M
665EOF
14f9c81f
YW
666 udevadm wait --settle --timeout=30 /dev/disk/by-partlabel/diskpart{1..4}
667 udevadm lock --device="${devices[0]}" mkfs.btrfs -d single -m raid1 -L "$label" -U "$uuid" /dev/disk/by-partlabel/diskpart{1..4}
668 udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label"
b1471e55 669 btrfs filesystem show
b1471e55 670 helper_check_device_symlinks
9c126b2c 671 helper_check_device_units
b1471e55 672 wipefs -a -f "${devices[0]}"
14f9c81f 673 udevadm wait --settle --timeout=30 --removed /dev/disk/by-partlabel/diskpart{1..4}
b1471e55
FS
674
675 echo "Multiple devices: using disks, data: raid10, metadata: raid10, mixed mode"
676 uuid="deadbeef-dead-dead-beef-000000000002"
677 label="btrfs_mdisk"
14f9c81f
YW
678 udevadm lock \
679 --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs0 \
680 --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs1 \
681 --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs2 \
682 --device=/dev/disk/by-id/ata-foobar_deadbeefbtrfs3 \
683 mkfs.btrfs -M -d raid10 -m raid10 -L "$label" -U "$uuid" "${devices[@]}"
684 udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label"
b1471e55 685 btrfs filesystem show
b1471e55 686 helper_check_device_symlinks
9c126b2c 687 helper_check_device_units
b1471e55
FS
688
689 echo "Multiple devices: using LUKS encrypted disks, data: raid1, metadata: raid1, mixed mode"
690 uuid="deadbeef-dead-dead-beef-000000000003"
691 label="btrfs_mencdisk"
692 mpoint="/btrfs_enc$RANDOM"
693 mkdir "$mpoint"
694 # Create a key-file
695 dd if=/dev/urandom of=/etc/btrfs_keyfile bs=64 count=1 iflag=fullblock
696 chmod 0600 /etc/btrfs_keyfile
697 # Encrypt each device and add it to /etc/crypttab, so it can be mounted
698 # automagically later
699 : >/etc/crypttab
700 for ((i = 0; i < ${#devices[@]}; i++)); do
701 # Intentionally use weaker cipher-related settings, since we don't care
702 # about security here as it's a throwaway LUKS partition
703 cryptsetup luksFormat -q \
704 --use-urandom --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \
705 --uuid "deadbeef-dead-dead-beef-11111111111$i" --label "encdisk$i" "${devices[$i]}" /etc/btrfs_keyfile
14f9c81f 706 udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-11111111111$i" "/dev/disk/by-label/encdisk$i"
b1471e55
FS
707 # Add the device into /etc/crypttab, reload systemd, and then activate
708 # the device so we can create a filesystem on it later
709 echo "encbtrfs$i UUID=deadbeef-dead-dead-beef-11111111111$i /etc/btrfs_keyfile luks,noearly" >>/etc/crypttab
710 systemctl daemon-reload
711 systemctl start "systemd-cryptsetup@encbtrfs$i"
712 done
713 helper_check_device_symlinks
9c126b2c 714 helper_check_device_units
b1471e55
FS
715 # Check if we have all necessary DM devices
716 ls -l /dev/mapper/encbtrfs{0..3}
717 # Create a multi-device btrfs filesystem on the LUKS devices
14f9c81f
YW
718 udevadm lock \
719 --device=/dev/mapper/encbtrfs0 \
720 --device=/dev/mapper/encbtrfs1 \
721 --device=/dev/mapper/encbtrfs2 \
722 --device=/dev/mapper/encbtrfs3 \
723 mkfs.btrfs -M -d raid1 -m raid1 -L "$label" -U "$uuid" /dev/mapper/encbtrfs{0..3}
724 udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label"
b1471e55 725 btrfs filesystem show
b1471e55 726 helper_check_device_symlinks
9c126b2c 727 helper_check_device_units
b1471e55
FS
728 # Mount it and write some data to it we can compare later
729 mount -t btrfs /dev/mapper/encbtrfs0 "$mpoint"
730 echo "hello there" >"$mpoint/test"
731 # "Deconstruct" the btrfs device and check if we're in a sane state (symlink-wise)
732 umount "$mpoint"
733 systemctl stop systemd-cryptsetup@encbtrfs{0..3}
14f9c81f 734 udevadm wait --settle --timeout=30 --removed "/dev/disk/by-uuid/$uuid"
b1471e55 735 helper_check_device_symlinks
9c126b2c 736 helper_check_device_units
b1471e55
FS
737 # Add the mount point to /etc/fstab and check if the device can be put together
738 # automagically. The source device is the DM name of the first LUKS device
739 # (from /etc/crypttab). We have to specify all LUKS devices manually, as
740 # registering the necessary devices is usually initrd's job (via btrfs device scan)
741 dev_stub="/dev/mapper/encbtrfs"
742 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
743 # Tell systemd about the new mount
744 systemctl daemon-reload
745 # Restart cryptsetup.target to trigger autounlock of partitions in /etc/crypttab
746 systemctl restart cryptsetup.target
747 # Start the corresponding mount unit and check if the btrfs device was reconstructed
748 # correctly
749 systemctl start "${mpoint##*/}.mount"
14f9c81f 750 udevadm wait --settle --timeout=30 "/dev/disk/by-uuid/$uuid" "/dev/disk/by-label/$label"
b1471e55 751 btrfs filesystem show
b1471e55 752 helper_check_device_symlinks
9c126b2c 753 helper_check_device_units
b1471e55
FS
754 grep "hello there" "$mpoint/test"
755 # Cleanup
756 systemctl stop "${mpoint##*/}.mount"
757 systemctl stop systemd-cryptsetup@encbtrfs{0..3}
758 sed -i "/${mpoint##*/}/d" /etc/fstab
759 : >/etc/crypttab
760 rm -fr "$mpoint"
761 systemctl daemon-reload
762 udevadm settle
763}
764
9cb41c33
FS
765testcase_iscsi_lvm() {
766 local dev i label link lun_id mpoint target_name uuid
767 local target_ip="127.0.0.1"
768 local target_port="3260"
769 local vgroup="iscsi_lvm$RANDOM"
770 local expected_symlinks=()
771 local devices=(
772 /dev/disk/by-id/ata-foobar_deadbeefiscsi{0..3}
773 )
774
775 ls -l "${devices[@]}"
776
777 # Start the target daemon
778 systemctl start tgtd
779 systemctl status tgtd
780
781 echo "iSCSI LUNs backed by devices"
782 # See RFC3721 and RFC7143
783 target_name="iqn.2021-09.com.example:iscsi.test"
784 # Initialize a new iSCSI target <$target_name> consisting of 4 LUNs, each
785 # backed by a device
786 tgtadm --lld iscsi --op new --mode target --tid=1 --targetname "$target_name"
787 for ((i = 0; i < ${#devices[@]}; i++)); do
788 # lun-0 is reserved by iSCSI
789 lun_id="$((i + 1))"
790 tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun "$lun_id" -b "${devices[$i]}"
791 tgtadm --lld iscsi --op update --mode logicalunit --tid 1 --lun "$lun_id"
792 expected_symlinks+=(
793 "/dev/disk/by-path/ip-$target_ip:$target_port-iscsi-$target_name-lun-$lun_id"
794 )
795 done
796 tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
797 # Configure the iSCSI initiator
798 iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover
799 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login
e529abe2 800 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
9cb41c33 801 helper_check_device_symlinks
9c126b2c 802 helper_check_device_units
9cb41c33
FS
803 # Cleanup
804 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout
805 tgtadm --lld iscsi --op delete --mode target --tid=1
806
807 echo "iSCSI LUNs backed by files + LVM"
808 # Note: we use files here to "trick" LVM the disks are indeed on a different
809 # host, so it doesn't automagically detect another path to the backing
810 # device once we disconnect the iSCSI devices
811 target_name="iqn.2021-09.com.example:iscsi.lvm.test"
812 mpoint="$(mktemp -d /iscsi_storeXXX)"
813 expected_symlinks=()
814 # Use the first device as it's configured with larger capacity
815 mkfs.ext4 -L iscsi_store "${devices[0]}"
14f9c81f 816 udevadm wait --settle --timeout=30 "${devices[0]}"
9cb41c33
FS
817 mount "${devices[0]}" "$mpoint"
818 for i in {1..4}; do
819 dd if=/dev/zero of="$mpoint/lun$i.img" bs=1M count=32
820 done
821 # Initialize a new iSCSI target <$target_name> consisting of 4 LUNs, each
822 # backed by a file
823 tgtadm --lld iscsi --op new --mode target --tid=2 --targetname "$target_name"
824 # lun-0 is reserved by iSCSI
825 for i in {1..4}; do
826 tgtadm --lld iscsi --op new --mode logicalunit --tid 2 --lun "$i" -b "$mpoint/lun$i.img"
827 tgtadm --lld iscsi --op update --mode logicalunit --tid 2 --lun "$i"
828 expected_symlinks+=(
829 "/dev/disk/by-path/ip-$target_ip:$target_port-iscsi-$target_name-lun-$i"
830 )
831 done
832 tgtadm --lld iscsi --op bind --mode target --tid 2 -I ALL
833 # Configure the iSCSI initiator
834 iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover
835 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login
e529abe2 836 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
9cb41c33 837 helper_check_device_symlinks
9c126b2c 838 helper_check_device_units
9cb41c33
FS
839 # Add all iSCSI devices into a LVM volume group, create two logical volumes,
840 # and check if necessary symlinks exist (and are valid)
841 lvm pvcreate -y "${expected_symlinks[@]}"
842 lvm pvs
843 lvm vgcreate "$vgroup" -y "${expected_symlinks[@]}"
844 lvm vgs
845 lvm vgchange -ay "$vgroup"
846 lvm lvcreate -y -L 4M "$vgroup" -n mypart1
847 lvm lvcreate -y -L 8M "$vgroup" -n mypart2
848 lvm lvs
14f9c81f 849 udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2"
9cb41c33 850 mkfs.ext4 -L mylvpart1 "/dev/$vgroup/mypart1"
14f9c81f 851 udevadm wait --settle --timeout=30 "/dev/disk/by-label/mylvpart1"
9cb41c33 852 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 853 helper_check_device_units
9cb41c33
FS
854 # Disconnect the iSCSI devices and check all the symlinks
855 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout
856 # "Reset" the DM state, since we yanked the backing storage from under the LVM,
857 # so the currently active VGs/LVs are invalid
858 dmsetup remove_all --deferred
9cb41c33 859 # The LVM and iSCSI related symlinks should be gone
e529abe2 860 udevadm wait --settle --timeout=30 --removed "/dev/$vgroup" "/dev/disk/by-label/mylvpart1" "${expected_symlinks[@]}"
9cb41c33 861 helper_check_device_symlinks "/dev/disk"
9c126b2c 862 helper_check_device_units
9cb41c33
FS
863 # Reconnect the iSCSI devices and check if everything get detected correctly
864 iscsiadm --mode discoverydb --type sendtargets --portal "$target_ip" --discover
865 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --login
14f9c81f 866 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}" "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2" "/dev/disk/by-label/mylvpart1"
9cb41c33 867 helper_check_device_symlinks "/dev/disk" "/dev/$vgroup"
9c126b2c 868 helper_check_device_units
9cb41c33
FS
869 # Cleanup
870 iscsiadm --mode node --targetname "$target_name" --portal "$target_ip:$target_port" --logout
871 tgtadm --lld iscsi --op delete --mode target --tid=2
872 umount "$mpoint"
873 rm -rf "$mpoint"
874}
f415cdb3
FS
875
876testcase_long_sysfs_path() {
98f8c316 877 local cursor link logfile mpoint
f415cdb3
FS
878 local expected_symlinks=(
879 "/dev/disk/by-label/data_vol"
880 "/dev/disk/by-label/swap_vol"
881 "/dev/disk/by-partlabel/test_swap"
882 "/dev/disk/by-partlabel/test_part"
883 "/dev/disk/by-partuuid/deadbeef-dead-dead-beef-000000000000"
884 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-111111111111"
885 "/dev/disk/by-uuid/deadbeef-dead-dead-beef-222222222222"
886 )
887
98f8c316
FS
888 # Create a cursor file to skip messages generated by udevd in initrd, as it
889 # might not be the same up-to-date version as we currently run (hence generating
890 # messages we check for later and making the test fail)
891 cursor="$(mktemp)"
892 journalctl --cursor-file="${cursor:?}" -n0 -q
893
f415cdb3
FS
894 # Make sure the test device is connected and show its "wonderful" path
895 stat /sys/block/vda
896 readlink -f /sys/block/vda/dev
897
14f9c81f 898 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
f415cdb3
FS
899
900 # Try to mount the data partition manually (using its label)
901 mpoint="$(mktemp -d /logsysfsXXX)"
902 mount LABEL=data_vol "$mpoint"
903 touch "$mpoint/test"
904 umount "$mpoint"
905 # Do the same, but with UUID and using fstab
906 echo "UUID=deadbeef-dead-dead-beef-222222222222 $mpoint ext4 defaults 0 0" >>/etc/fstab
907 systemctl daemon-reload
908 mount "$mpoint"
03f5e9b2 909 timeout 30 bash -c "while ! systemctl -q is-active '$mpoint'; do sleep .2; done"
f415cdb3
FS
910 test -e "$mpoint/test"
911 umount "$mpoint"
912
913 # Test out the swap partition
914 swapon -v -L swap_vol
915 swapoff -v -L swap_vol
916
7b3a1af0
FS
917 udevadm settle
918
f415cdb3 919 logfile="$(mktemp)"
98f8c316
FS
920 # Check state of affairs after https://github.com/systemd/systemd/pull/22759
921 # Note: can't use `--cursor-file` here, since we don't want to update the cursor
922 # after using it
923 [[ "$(journalctl --after-cursor="$(<"$cursor")" -q --no-pager -o short-monotonic -p info --grep "Device path.*vda.?' too long to fit into unit name" | wc -l)" -eq 0 ]]
924 [[ "$(journalctl --after-cursor="$(<"$cursor")" -q --no-pager -o short-monotonic --grep "Unit name .*vda.?\.device\" too long, falling back to hashed unit name" | wc -l)" -gt 0 ]]
925 # Check if the respective "hashed" units exist and are active (plugged)
926 systemctl status --no-pager "$(readlink -f /sys/block/vda/vda1)"
927 systemctl status --no-pager "$(readlink -f /sys/block/vda/vda2)"
f415cdb3 928 # Make sure we don't unnecessarily spam the log
b26f4f00 929 { 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
930 [[ "$(wc -l <"$logfile")" -lt 10 ]]
931
932 : >/etc/fstab
98f8c316 933 rm -fr "${cursor:?}" "${logfile:?}" "${mpoint:?}"
f415cdb3
FS
934}
935
3c9af05c 936testcase_mdadm_basic() {
18161cf0 937 local i part_name raid_name raid_dev uuid
3c9af05c
FS
938 local expected_symlinks=()
939 local devices=(
940 /dev/disk/by-id/ata-foobar_deadbeefmdadm{0..4}
941 )
942
943 ls -l "${devices[@]}"
944
1bb38875 945 echo "Mirror raid (RAID 1)"
3c9af05c 946 raid_name="mdmirror"
1bb38875
FS
947 raid_dev="/dev/md/$raid_name"
948 part_name="${raid_name}_part"
3c9af05c
FS
949 uuid="aaaaaaaa:bbbbbbbb:cccccccc:00000001"
950 expected_symlinks=(
1bb38875
FS
951 "$raid_dev"
952 "/dev/disk/by-id/md-name-H:$raid_name"
3c9af05c 953 "/dev/disk/by-id/md-uuid-$uuid"
1bb38875 954 "/dev/disk/by-label/$part_name" # ext4 partition
3c9af05c
FS
955 )
956 # Create a simple RAID 1 with an ext4 filesystem
1bb38875
FS
957 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
958 udevadm wait --settle --timeout=30 "$raid_dev"
959 mkfs.ext4 -L "$part_name" "$raid_dev"
3c9af05c 960 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
18161cf0
FS
961 for i in {0..9}; do
962 echo "Disassemble - reassemble loop, iteration #$i"
963 mdadm -v --stop "$raid_dev"
964 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
965 mdadm --assemble "$raid_dev" --name "$raid_name" -v
966 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
967 done
1bb38875 968 helper_check_device_symlinks
9c126b2c 969 helper_check_device_units
1bb38875
FS
970 # Cleanup
971 mdadm -v --stop "$raid_dev"
18161cf0 972 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
1bb38875
FS
973
974 echo "Parity raid (RAID 5)"
975 raid_name="mdparity"
976 raid_dev="/dev/md/$raid_name"
977 part_name="${raid_name}_part"
978 uuid="aaaaaaaa:bbbbbbbb:cccccccc:00000101"
979 expected_symlinks=(
980 "$raid_dev"
981 "/dev/disk/by-id/md-name-H:$raid_name"
982 "/dev/disk/by-id/md-uuid-$uuid"
983 "/dev/disk/by-label/$part_name" # ext4 partition
984 )
985 # Create a simple RAID 5 with an ext4 filesystem
986 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
987 udevadm wait --settle --timeout=30 "$raid_dev"
988 mkfs.ext4 -L "$part_name" "$raid_dev"
989 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
18161cf0
FS
990 for i in {0..9}; do
991 echo "Disassemble - reassemble loop, iteration #$i"
992 mdadm -v --stop "$raid_dev"
993 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
994 mdadm --assemble "$raid_dev" --name "$raid_name" -v
995 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
996 done
1bb38875 997 helper_check_device_symlinks
9c126b2c 998 helper_check_device_units
1bb38875
FS
999 # Cleanup
1000 mdadm -v --stop "$raid_dev"
18161cf0 1001 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
9c126b2c 1002 helper_check_device_units
1bb38875 1003
18161cf0 1004 echo "Mirror + parity raid (RAID 10) + multiple partitions"
1bb38875
FS
1005 raid_name="mdmirpar"
1006 raid_dev="/dev/md/$raid_name"
1007 part_name="${raid_name}_part"
1008 uuid="aaaaaaaa:bbbbbbbb:cccccccc:00001010"
1009 expected_symlinks=(
1010 "$raid_dev"
1011 "/dev/disk/by-id/md-name-H:$raid_name"
1012 "/dev/disk/by-id/md-uuid-$uuid"
1013 "/dev/disk/by-label/$part_name" # ext4 partition
18161cf0
FS
1014 # Partitions
1015 "${raid_dev}1"
1016 "${raid_dev}2"
1017 "${raid_dev}3"
1018 "/dev/disk/by-id/md-name-H:$raid_name-part1"
1019 "/dev/disk/by-id/md-name-H:$raid_name-part2"
1020 "/dev/disk/by-id/md-name-H:$raid_name-part3"
1021 "/dev/disk/by-id/md-uuid-$uuid-part1"
1022 "/dev/disk/by-id/md-uuid-$uuid-part2"
1023 "/dev/disk/by-id/md-uuid-$uuid-part3"
1bb38875
FS
1024 )
1025 # Create a simple RAID 10 with an ext4 filesystem
1026 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
1027 udevadm wait --settle --timeout=30 "$raid_dev"
18161cf0
FS
1028 # Partition the raid device
1029 # Here, 'udevadm lock' is meaningless, as udevd does not lock MD devices.
1030 sfdisk --wipe=always "$raid_dev" <<EOF
1031label: gpt
1032
1033uuid="deadbeef-dead-dead-beef-111111111111", name="mdpart1", size=8M
1034uuid="deadbeef-dead-dead-beef-222222222222", name="mdpart2", size=32M
1035uuid="deadbeef-dead-dead-beef-333333333333", name="mdpart3", size=16M
1036EOF
1037 udevadm wait --settle --timeout=30 "/dev/disk/by-id/md-uuid-$uuid-part2"
1038 mkfs.ext4 -L "$part_name" "/dev/disk/by-id/md-uuid-$uuid-part2"
d3ce9bed 1039 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
18161cf0
FS
1040 for i in {0..9}; do
1041 echo "Disassemble - reassemble loop, iteration #$i"
1042 mdadm -v --stop "$raid_dev"
1043 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
1044 mdadm --assemble "$raid_dev" --name "$raid_name" -v
1045 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
1046 done
d3ce9bed 1047 helper_check_device_symlinks
9c126b2c 1048 helper_check_device_units
18161cf0
FS
1049 # Cleanup
1050 mdadm -v --stop "$raid_dev"
1051 # Check if all expected symlinks were removed after the cleanup
1052 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
9c126b2c 1053 helper_check_device_units
d3ce9bed
FS
1054}
1055
1056testcase_mdadm_lvm() {
1057 local part_name raid_name raid_dev uuid vgroup
1058 local expected_symlinks=()
1059 local devices=(
1060 /dev/disk/by-id/ata-foobar_deadbeefmdadmlvm{0..4}
1061 )
1062
1063 ls -l "${devices[@]}"
1064
1065 raid_name="mdlvm"
1066 raid_dev="/dev/md/$raid_name"
1067 part_name="${raid_name}_part"
1068 vgroup="${raid_name}_vg"
1069 uuid="aaaaaaaa:bbbbbbbb:ffffffff:00001010"
1070 expected_symlinks=(
1071 "$raid_dev"
1072 "/dev/$vgroup/mypart1" # LVM partition
1073 "/dev/$vgroup/mypart2" # LVM partition
1074 "/dev/disk/by-id/md-name-H:$raid_name"
1075 "/dev/disk/by-id/md-uuid-$uuid"
1076 "/dev/disk/by-label/$part_name" # ext4 partition
1077 )
1078 # Create a RAID 10 with LVM + ext4
1079 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
1080 udevadm wait --settle --timeout=30 "$raid_dev"
1081 # Create an LVM on the MD
1082 lvm pvcreate -y "$raid_dev"
1083 lvm pvs
1084 lvm vgcreate "$vgroup" -y "$raid_dev"
1085 lvm vgs
1086 lvm vgchange -ay "$vgroup"
1087 lvm lvcreate -y -L 4M "$vgroup" -n mypart1
1088 lvm lvcreate -y -L 8M "$vgroup" -n mypart2
1089 lvm lvs
1090 udevadm wait --settle --timeout=30 "/dev/$vgroup/mypart1" "/dev/$vgroup/mypart2"
1091 mkfs.ext4 -L "$part_name" "/dev/$vgroup/mypart2"
1092 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
1093 # Disassemble the array
1094 lvm vgchange -an "$vgroup"
1095 mdadm -v --stop "$raid_dev"
6d49e094 1096 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
d3ce9bed 1097 helper_check_device_symlinks
9c126b2c 1098 helper_check_device_units
d3ce9bed 1099 # Reassemble it and check if all required symlinks exist
1bb38875 1100 mdadm --assemble "$raid_dev" --name "$raid_name" -v
3c9af05c
FS
1101 udevadm wait --settle --timeout=30 "${expected_symlinks[@]}"
1102 helper_check_device_symlinks
9c126b2c 1103 helper_check_device_units
6d49e094
FS
1104 # Cleanup
1105 lvm vgchange -an "$vgroup"
1106 mdadm -v --stop "$raid_dev"
1107 # Check if all expected symlinks were removed after the cleanup
1108 udevadm wait --settle --timeout=30 --removed "${expected_symlinks[@]}"
9c126b2c 1109 helper_check_device_units
3c9af05c
FS
1110}
1111
f2204ac2
FS
1112: >/failed
1113
1114udevadm settle
8a088877 1115udevadm control --log-level debug
f2204ac2
FS
1116lsblk -a
1117
d430e451
FS
1118echo "Check if all symlinks under /dev/disk/ are valid (pre-test)"
1119helper_check_device_symlinks
1120
f2204ac2
FS
1121# TEST_FUNCTION_NAME is passed on the kernel command line via systemd.setenv=
1122# in the respective test.sh file
1123if ! command -v "${TEST_FUNCTION_NAME:?}"; then
1124 echo >&2 "Missing verification handler for test case '$TEST_FUNCTION_NAME'"
1125 exit 1
1126fi
1127
1128echo "TEST_FUNCTION_NAME=$TEST_FUNCTION_NAME"
1129"$TEST_FUNCTION_NAME"
f415cdb3 1130udevadm settle
f2204ac2 1131
d430e451
FS
1132echo "Check if all symlinks under /dev/disk/ are valid (post-test)"
1133helper_check_device_symlinks
1134
8a088877
YW
1135udevadm control --log-level info
1136
f2204ac2
FS
1137systemctl status systemd-udevd
1138
1139touch /testok
1140rm /failed