From 41d1aaea6425abb10ef82bc6065a70da376e4fbf Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 11 Mar 2022 18:15:03 +0100 Subject: [PATCH] test: use flock when calling mkfs.btrfs As stated in https://github.com/systemd/systemd/issues/21819#issuecomment-1064377645 `mkfs.btrfs` doesn't hold the lock for the whole duration of `mkfs.btrfs`, thus causing unexpected races & test fails. Let's wrap the `mkfs.btrfs` calls in an flock wrapper to mitigate this. Hopefully fixes: #21819 --- test/test-functions | 1 + test/units/testsuite-64.sh | 50 +++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/test/test-functions b/test/test-functions index 6619a7a44b0..c734a15ca91 100644 --- a/test/test-functions +++ b/test/test-functions @@ -141,6 +141,7 @@ BASICTOOLS=( echo env false + flock getconf getent getfacl diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh index dc8b263b100..58b6157e6ff 100755 --- a/test/units/testsuite-64.sh +++ b/test/units/testsuite-64.sh @@ -148,6 +148,42 @@ helper_wait_for_pvscan() { return 1 } +# Generate an `flock` command line for a device list +# +# This is useful mainly for mkfs.btrfs, which doesn't hold the lock on each +# device for the entire duration of mkfs.btrfs, causing weird races between udev +# and mkfs.btrfs. This function creates an array of chained flock calls to take +# the lock of all involved devices, which can be then used in combination with +# mkfs.btrfs to mitigate the issue. +# +# For example, calling: +# helper_generate_flock_cmdline my_array /dev/loop1 /dev/loop2 /dev/loop3 +# +# will result in "${my_array[@]}" containing: +# flock -x /dev/loop1 flock -x /dev/loop2 flock -x /dev/loop3 +# +# Note: the array will be CLEARED before the first assignment +# +# Arguments: +# $1 - NAME of an array in which the commands/argument will be stored +# $2-$n - path to devices +helper_generate_flock_cmdline() { + # Create a name reference to the array passed as the first argument + # (requires bash 4.3+) + local -n cmd_array="${1:?}" + shift + + if [[ $# -eq 0 ]]; then + echo >&2 "Missing argument(s): device path(s)" + return 1 + fi + + cmd_array=() + for dev in "$@"; do + cmd_array+=("flock" "-x" "$dev") + done +} + testcase_megasas2_basic() { lsblk -S [[ "$(lsblk --scsi --noheadings | wc -l)" -ge 128 ]] @@ -388,6 +424,7 @@ testcase_lvm_basic() { testcase_btrfs_basic() { local dev_stub i label mpoint uuid + local flock_cmd=() local devices=( /dev/disk/by-id/ata-foobar_deadbeefbtrfs{0..3} ) @@ -397,7 +434,8 @@ testcase_btrfs_basic() { echo "Single device: default settings" uuid="deadbeef-dead-dead-beef-000000000000" label="btrfs_root" - mkfs.btrfs -L "$label" -U "$uuid" "${devices[0]}" + helper_generate_flock_cmdline flock_cmd "${devices[0]}" + "${flock_cmd[@]}" mkfs.btrfs -L "$label" -U "$uuid" "${devices[0]}" udevadm settle btrfs filesystem show test -e "/dev/disk/by-uuid/$uuid" @@ -416,7 +454,9 @@ name="diskpart3", size=85M name="diskpart4", size=85M EOF udevadm settle - mkfs.btrfs -d single -m raid1 -L "$label" -U "$uuid" /dev/disk/by-partlabel/diskpart{1..4} + # We need to flock only the device itself, not its partitions + helper_generate_flock_cmdline flock_cmd "${devices[0]}" + "${flock_cmd[@]}" mkfs.btrfs -d single -m raid1 -L "$label" -U "$uuid" /dev/disk/by-partlabel/diskpart{1..4} udevadm settle btrfs filesystem show test -e "/dev/disk/by-uuid/$uuid" @@ -427,7 +467,8 @@ EOF echo "Multiple devices: using disks, data: raid10, metadata: raid10, mixed mode" uuid="deadbeef-dead-dead-beef-000000000002" label="btrfs_mdisk" - mkfs.btrfs -M -d raid10 -m raid10 -L "$label" -U "$uuid" "${devices[@]}" + helper_generate_flock_cmdline flock_cmd "${devices[@]}" + "${flock_cmd[@]}" mkfs.btrfs -M -d raid10 -m raid10 -L "$label" -U "$uuid" "${devices[@]}" udevadm settle btrfs filesystem show test -e "/dev/disk/by-uuid/$uuid" @@ -464,7 +505,8 @@ EOF # Check if we have all necessary DM devices ls -l /dev/mapper/encbtrfs{0..3} # Create a multi-device btrfs filesystem on the LUKS devices - mkfs.btrfs -M -d raid1 -m raid1 -L "$label" -U "$uuid" /dev/mapper/encbtrfs{0..3} + helper_generate_flock_cmdline flock_cmd /dev/mapper/encbtrfs{0..3} + "${flock_cmd[@]}" mkfs.btrfs -M -d raid1 -m raid1 -L "$label" -U "$uuid" /dev/mapper/encbtrfs{0..3} udevadm settle btrfs filesystem show test -e "/dev/disk/by-uuid/$uuid"