]>
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")" | |
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 |
43 | helper_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 |
83 | check_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 | ||
131 | check_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 | ||
156 | helper_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 |
171 | testcase_megasas2_basic() { |
172 | lsblk -S | |
173 | [[ "$(lsblk --scsi --noheadings | wc -l)" -ge 128 ]] | |
174 | } | |
175 | ||
176 | testcase_nvme_basic() { | |
177 | lsblk --noheadings | grep "^nvme" | |
178 | [[ "$(lsblk --noheadings | grep -c "^nvme")" -ge 28 ]] | |
179 | } | |
180 | ||
6788418a FS |
181 | testcase_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 | 193 | testcase_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 |
206 | testcase_multipath_basic_failover() { |
207 | local dmpath i path wwid | |
208 | ||
209 | # Configure multipath | |
210 | cat >/etc/multipath.conf <<\EOF | |
211 | defaults { | |
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 | ||
218 | blacklist_exceptions { | |
219 | property "(SCSI_IDENT_|ID_WWN)" | |
220 | } | |
221 | ||
222 | blacklist { | |
223 | } | |
224 | EOF | |
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 | 305 | testcase_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) |
341 | EOF | |
342 | ||
343 | rule=/run/udev/rules.d/50-test.rules | |
344 | mkdir -p "${rule%/*}" | |
345 | cat >"$rule" <<EOF | |
346 | SUBSYSTEM=="block", KERNEL=="${devices[4]##*/}*|${devices[5]##*/}*", OPTIONS="link_priority=10" | |
35497c7c FS |
347 | EOF |
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 |
398 | testcase_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) | |
430 | EOF | |
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 | ||
460 | testcase_simultaneous_events() { | |
461 | testcase_simultaneous_events_1 | |
462 | testcase_simultaneous_events_2 | |
463 | } | |
464 | ||
0203b2e4 | 465 | testcase_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 |
638 | testcase_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 |
659 | label: gpt |
660 | ||
661 | name="diskpart1", size=85M | |
662 | name="diskpart2", size=85M | |
663 | name="diskpart3", size=85M | |
664 | name="diskpart4", size=85M | |
665 | EOF | |
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 |
765 | testcase_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 | |
876 | testcase_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 | 936 | testcase_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 | |
1031 | label: gpt | |
1032 | ||
1033 | uuid="deadbeef-dead-dead-beef-111111111111", name="mdpart1", size=8M | |
1034 | uuid="deadbeef-dead-dead-beef-222222222222", name="mdpart2", size=32M | |
1035 | uuid="deadbeef-dead-dead-beef-333333333333", name="mdpart3", size=16M | |
1036 | EOF | |
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 | ||
1056 | testcase_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 | ||
1114 | udevadm settle | |
8a088877 | 1115 | udevadm control --log-level debug |
f2204ac2 FS |
1116 | lsblk -a |
1117 | ||
d430e451 FS |
1118 | echo "Check if all symlinks under /dev/disk/ are valid (pre-test)" |
1119 | helper_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 | |
1123 | if ! command -v "${TEST_FUNCTION_NAME:?}"; then | |
1124 | echo >&2 "Missing verification handler for test case '$TEST_FUNCTION_NAME'" | |
1125 | exit 1 | |
1126 | fi | |
1127 | ||
1128 | echo "TEST_FUNCTION_NAME=$TEST_FUNCTION_NAME" | |
1129 | "$TEST_FUNCTION_NAME" | |
f415cdb3 | 1130 | udevadm settle |
f2204ac2 | 1131 | |
d430e451 FS |
1132 | echo "Check if all symlinks under /dev/disk/ are valid (post-test)" |
1133 | helper_check_device_symlinks | |
1134 | ||
8a088877 YW |
1135 | udevadm control --log-level info |
1136 | ||
f2204ac2 FS |
1137 | systemctl status systemd-udevd |
1138 | ||
1139 | touch /testok | |
1140 | rm /failed |