From 256f011d2f256c8c2c05c37a518401199fa423bf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 1 Nov 2023 05:09:40 +0100 Subject: Merging upstream version 4.2+20231026. Signed-off-by: Daniel Baumann --- tests/00confnames | 107 +++++++++++++++++++++++++++++++++ tests/00createnames | 89 ++++++--------------------- tests/06name | 4 +- tests/23rdev-lifetime | 34 +++++++++++ tests/24raid10deadlock | 88 +++++++++++++++++++++++++++ tests/24raid10deadlock.inject_error | 0 tests/24raid456deadlock | 58 ++++++++++++++++++ tests/25raid456-recovery-while-reshape | 33 ++++++++++ tests/25raid456-reshape-corrupt-data | 35 +++++++++++ tests/25raid456-reshape-deadlock | 34 +++++++++++ tests/25raid456-reshape-while-recovery | 32 ++++++++++ tests/func.sh | 1 - tests/templates/names_template | 80 ++++++++++++++++++++++++ 13 files changed, 523 insertions(+), 72 deletions(-) create mode 100644 tests/00confnames create mode 100644 tests/23rdev-lifetime create mode 100644 tests/24raid10deadlock create mode 100644 tests/24raid10deadlock.inject_error create mode 100644 tests/24raid456deadlock create mode 100644 tests/25raid456-recovery-while-reshape create mode 100644 tests/25raid456-reshape-corrupt-data create mode 100644 tests/25raid456-reshape-deadlock create mode 100644 tests/25raid456-reshape-while-recovery create mode 100644 tests/templates/names_template (limited to 'tests') diff --git a/tests/00confnames b/tests/00confnames new file mode 100644 index 0000000..10823f0 --- /dev/null +++ b/tests/00confnames @@ -0,0 +1,107 @@ +set -x -e +. tests/templates/names_template + +# Test how and from config are handled during Incremental assemblation. +# 1-6 only tests (no in config). +# 6-10 and combinations are tested. +# 11-13 corner cases. + +names_create "/dev/md/name" +local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)" +[[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1 + + +# 1. definition consistent with metadata name. +names_make_conf $_UUID "/dev/md/name" "empty" $config +mdadm -S "/dev/md127" +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 2. Same as 1, but use short name form of . +names_make_conf $_UUID "name" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 3. Same as 1, but use different than metadata provides. +names_make_conf $_UUID "/dev/md/other" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "other" "name" +mdadm -S "/dev/md127" + +# 4. Same as 3, but use short name form of . +names_make_conf $_UUID "other" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "other" "name" +mdadm -S "/dev/md127" + +# 5. Force particular node creation by setting to /dev/mdX. Link is not created in this +# case. +names_make_conf $_UUID "/dev/md4" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md4" "empty" "name" +mdadm -S "/dev/md4" + +# 6. set to /dev/mdX, same as in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "/dev/md22" "name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 7. set to /dev/mdX, different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "/dev/md8" "other" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 8. Both and different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "devnode" "other_name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 9. set to metadata name, different than in metadata. +# Metadata name and default node used - controversial. Current behavior documented. +names_make_conf $_UUID "name" "other_name" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 10. Bad set, no . +# Metadata name and default node used - expected. +names_make_conf $_UUID "/im/bad/devname" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 11. with some special symbols and locales, no . +# should be ignored. +names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 12. No and set. +# Metadata name and default node used - expected. +names_make_conf $_UUID "empty" "empty" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 13. No , set to /dev/mdX. +# Entry should be ignored, it is not ignored but result is good anyway. +names_make_conf $_UUID "empty" "/dev/md12" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" + +# 13. No , with special symbols and locales. +# Entry should be ignored, it is not ignored but result is good anyway. +names_make_conf $_UUID "empty" "./\śćń#&" $config +mdadm -I $dev0 --config=$config +names_verify "/dev/md127" "name" "name" +mdadm -S "/dev/md127" diff --git a/tests/00createnames b/tests/00createnames index 64b81b9..a95e7d2 100644 --- a/tests/00createnames +++ b/tests/00createnames @@ -1,93 +1,44 @@ set -x -e +. tests/templates/names_template # Test how and --name= are handled for create mode. -# We need to check three properties, generated from those parameters: -# - devnode name -# - link in /dev/md/ (MD_DEVNAME property from --detail --export) -# - name in metadata (MD_NAME property from --examine --export) - -function _verify() { - local DEVNODE_NAME="$1" - local WANTED_LINK="$2" - local WANTED_NAME="$3" - - local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" - if [[ "$?" != "0" ]]; then - echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." - exit 1 - fi - - if [[ "$WANTED_LINK" != "empty" ]]; then - local EXPECTED="MD_DEVNAME=$WANTED_LINK" - if [[ "$RES" != "$EXPECTED" ]]; then - echo "$RES doesn't match $EXPECTED." - exit 1 - fi - fi - - - local RES="$(mdadm -E --export $dev0 | grep MD_NAME)" - if [[ "$?" != "0" ]]; then - echo "Cannot get metadata from $dev0." - exit 1 - fi - - local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" - if [[ "$RES" != "$EXPECTED" ]]; then - echo "$RES doesn't match $EXPECTED." - exit 1 - fi -} - -function _create() { - local DEVNAME=$1 - local NAME=$2 - - if [[ -z "$NAME" ]]; then - mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force - else - mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force - fi - - if [[ "$?" != "0" ]]; then - echo "Cannot create device." - exit 1 - fi -} # The most trivial case. -_create "/dev/md/name" -_verify "/dev/md127" "name" "name" +names_create "/dev/md/name" +names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" -_create "name" -_verify "/dev/md127" "name" "name" +names_create "name" +names_verify "/dev/md127" "name" "name" mdadm -S "/dev/md127" # Use 'mdX' as name. -_create "/dev/md/md0" -_verify "/dev/md127" "md0" "md0" +names_create "/dev/md/md0" +names_verify "/dev/md127" "md0" "md0" mdadm -S "/dev/md127" -_create "md0" -_verify "/dev/md127" "md0" "md0" +names_create "md0" +names_verify "/dev/md127" "md0" "md0" mdadm -S "/dev/md127" # is used to create MD_DEVNAME but, name is used to create MD_NAME. -_create "/dev/md/devnode" "name" -_verify "/dev/md127" "devnode" "name" +names_create "/dev/md/devnode" "name" +names_verify "/dev/md127" "devnode" "name" mdadm -S "/dev/md127" -_create "devnode" "name" -_verify "/dev/md127" "devnode" "name" +names_create "devnode" "name" +names_verify "/dev/md127" "devnode" "name" mdadm -S "/dev/md127" # Devnode points to /dev/ directory. MD_DEVNAME doesn't exist. -_create "/dev/md0" -_verify "/dev/md0" "empty" "0" +names_create "/dev/md0" +names_verify "/dev/md0" "empty" "0" mdadm -S "/dev/md0" # Devnode points to /dev/ directory and name is set. -_create "/dev/md0" "name" -_verify "/dev/md0" "empty" "name" +names_create "/dev/md0" "name" +names_verify "/dev/md0" "empty" "name" mdadm -S "/dev/md0" + +# Devnode is a special ignore keyword. Should be rejected. +names_create "" "name", "true" diff --git a/tests/06name b/tests/06name index 4d5e824..86eaab6 100644 --- a/tests/06name +++ b/tests/06name @@ -3,8 +3,8 @@ set -x # create an array with a name mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1 -mdadm -E $dev0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1 -mdadm -D $md0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1 +mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1 +mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1 mdadm -S $md0 mdadm -A $md0 --name="Fred" $devlist diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime new file mode 100644 index 0000000..1750b0d --- /dev/null +++ b/tests/23rdev-lifetime @@ -0,0 +1,34 @@ +devname=${dev0##*/} +devt=`cat /sys/block/$devname/dev` +pid="" +runtime=2 + +clean_up_test() { + pill -9 $pid + echo clear > /sys/block/md0/md/array_state +} + +trap 'clean_up_test' EXIT + +add_by_sysfs() { + while true; do + echo $devt > /sys/block/md0/md/new_dev + done +} + +remove_by_sysfs(){ + while true; do + echo remove > /sys/block/md0/md/dev-${devname}/state + done +} + +echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed" + +add_by_sysfs & +pid="$pid $!" + +remove_by_sysfs & +pid="$pid $!" + +sleep $runtime +exit 0 diff --git a/tests/24raid10deadlock b/tests/24raid10deadlock new file mode 100644 index 0000000..ee330aa --- /dev/null +++ b/tests/24raid10deadlock @@ -0,0 +1,88 @@ +devs="$dev0 $dev1 $dev2 $dev3" +runtime=120 +pid="" +action_pid="" + +set_up_injection() +{ + echo -1 > /sys/kernel/debug/fail_make_request/times + echo 1 > /sys/kernel/debug/fail_make_request/probability + echo 0 > /sys/kernel/debug/fail_make_request/verbose + echo 1 > /sys/block/${1##*/}/make-it-fail +} + +clean_up_injection() +{ + echo 0 > /sys/block/${1##*/}/make-it-fail + echo 0 > /sys/kernel/debug/fail_make_request/times + echo 0 > /sys/kernel/debug/fail_make_request/probability + echo 2 > /sys/kernel/debug/fail_make_request/verbose +} + +test_rdev() +{ + while true; do + mdadm -f $md0 $1 &> /dev/null + mdadm -r $md0 $1 &> /dev/null + mdadm --zero-superblock $1 &> /dev/null + mdadm -a $md0 $1 &> /dev/null + sleep $2 + done +} + +test_write_action() +{ + while true; do + echo frozen > /sys/block/md0/md/sync_action + echo idle > /sys/block/md0/md/sync_action + sleep 0.1 + done +} + +set_up_test() +{ + fio -h &> /dev/null || die "fio not found" + + # create a simple raid10 + mdadm -Cv -R -n 4 -l10 $md0 $devs || die "create raid10 failed" +} + +clean_up_test() +{ + clean_up_injection $dev0 + pkill -9 fio + kill -9 $pid + kill -9 $action_pid + + sleep 1 + + if ps $action_pid | tail -1 | awk '{print $3}' | grep D; then + die "thread that is writing sysfs is stuck in D state, deadlock is triggered" + fi + mdadm -S $md0 +} + +cat /sys/kernel/debug/fail_make_request/times || die "fault injection is not enabled" + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +# backgroup io pressure +fio -filename=$md0 -rw=randwrite -direct=1 -name=test -bs=4k -numjobs=16 -iodepth=16 & + +# trigger add/remove device by io failure +set_up_injection $dev0 +test_rdev $dev0 2 & +pid="$pid $!" + +# add/remove device directly +test_rdev $dev3 10 & +pid="$pid $!" + +test_write_action & +action_pid="$!" + +sleep $runtime + +exit 0 diff --git a/tests/24raid10deadlock.inject_error b/tests/24raid10deadlock.inject_error new file mode 100644 index 0000000..e69de29 diff --git a/tests/24raid456deadlock b/tests/24raid456deadlock new file mode 100644 index 0000000..80e6e97 --- /dev/null +++ b/tests/24raid456deadlock @@ -0,0 +1,58 @@ +devs="$dev0 $dev1 $dev2 $dev3 $dev4 $dev5" +runtime=120 +pid="" +old=`cat /proc/sys/vm/dirty_background_ratio` + +test_write_action() +{ + while true; do + echo check > /sys/block/md0/md/sync_action &> /dev/null + sleep 0.1 + echo idle > /sys/block/md0/md/sync_action &> /dev/null + done +} + +test_write_back() +{ + fio -filename=$md0 -bs=4k -rw=write -numjobs=1 -name=test \ + -time_based -runtime=$runtime &> /dev/null +} + +set_up_test() +{ + fio -h &> /dev/null || die "fio not found" + + # create a simple raid6 + mdadm -Cv -R -n 6 -l6 $md0 $devs --assume-clean || die "create raid6 failed" + + # trigger dirty pages write back + echo 0 > /proc/sys/vm/dirty_background_ratio +} + +clean_up_test() +{ + echo $old > /proc/sys/vm/dirty_background_ratio + + pkill -9 fio + kill -9 $pid + + sleep 1 + + if ps $pid | tail -1 | awk '{print $3}' | grep D; then + die "thread that is writing sysfs is stuck in D state, deadlock is triggered" + fi + mdadm -S $md0 +} + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +test_write_back & + +test_write_action & +pid="$!" + +sleep $runtime + +exit 0 diff --git a/tests/25raid456-recovery-while-reshape b/tests/25raid456-recovery-while-reshape new file mode 100644 index 0000000..3f6251b --- /dev/null +++ b/tests/25raid456-recovery-while-reshape @@ -0,0 +1,33 @@ +devs="$dev0 $dev1 $dev2" + +set_up_test() +{ + mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed" + mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array" + echo 1000 > /sys/block/md0/md/sync_speed_max +} + +clean_up_test() +{ + mdadm -S $md0 +} + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +# trigger reshape +mdadm --grow -l 6 $md0 +sleep 1 + +# set up replacement +echo frozen > /sys/block/md0/md/sync_action +echo want_replacement > /sys/block/md0/md/rd0/state +echo reshape > /sys/block/md0/md/sync_action +sleep 1 + +# reassemeble array +mdadm -S $md0 || die "can't stop array" +mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array" + +exit 0 diff --git a/tests/25raid456-reshape-corrupt-data b/tests/25raid456-reshape-corrupt-data new file mode 100644 index 0000000..fdb875f --- /dev/null +++ b/tests/25raid456-reshape-corrupt-data @@ -0,0 +1,35 @@ +devs="$dev0 $dev1 $dev2" + +set_up_test() +{ + mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed" + mdadm -a $md0 $dev3 || die "failed to bind new disk to array" + mkfs.xfs -f $md0 || die "mkfs failed" + xfs_ncheck $md0 || die "check fs failed" +} + +clean_up_test() +{ + mdadm -S $md0 +} + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +# trigger reshape +echo 1000 > /sys/block/md0/md/sync_speed_max +mdadm --grow -l 6 $md0 +sleep 1 + +# stop and start reshape +echo frozen > /sys/block/md0/md/sync_action +echo system > /sys/block/md0/md/sync_speed_max +echo reshape > /sys/block/md0/md/sync_action + +mdadm -W $md0 + +# check if data is corrupted +xfs_ncheck $md0 || die "data is corrupted after reshape" + +exit 0 diff --git a/tests/25raid456-reshape-deadlock b/tests/25raid456-reshape-deadlock new file mode 100644 index 0000000..bfa0cc5 --- /dev/null +++ b/tests/25raid456-reshape-deadlock @@ -0,0 +1,34 @@ +devs="$dev0 $dev1 $dev2" + +set_up_test() +{ + mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed" + mdadm -a $md0 $dev3 || die "failed to bind new disk to array" + echo 1000 > /sys/block/md0/md/sync_speed_max +} + +clean_up_test() +{ + echo idle > /sys/block/md0/md/sync_action + mdadm -S $md0 +} + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +# trigger reshape +mdadm --grow -l 6 $md0 +sleep 1 + +# stop reshape +echo frozen > /sys/block/md0/md/sync_action + +# read accross reshape +dd if=$md0 of=/dev/NULL bs=1m count=100 iflag=direct &> /dev/null & +sleep 2 + +# suspend array +echo 1 > /sys/block/md0/md/suspend_lo + +exit 0 diff --git a/tests/25raid456-reshape-while-recovery b/tests/25raid456-reshape-while-recovery new file mode 100644 index 0000000..b9f871f --- /dev/null +++ b/tests/25raid456-reshape-while-recovery @@ -0,0 +1,32 @@ +devs="$dev0 $dev1 $dev2" + +set_up_test() +{ + mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed" + mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array" + echo 1000 > /sys/block/md0/md/sync_speed_max +} + +clean_up_test() +{ + mdadm -S $md0 +} + +trap 'clean_up_test' EXIT + +set_up_test || die "set up test failed" + +# set up replacement +echo want_replacement > /sys/block/md0/md/rd0/state +sleep 1 + +# trigger reshape +echo frozen > /sys/block/md0/md/sync_action +mdadm --grow -l 6 $md0 +sleep 1 + +# reassemeble array +mdadm -S $md0 || die "can't stop array" +mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array" + +exit 0 diff --git a/tests/func.sh b/tests/func.sh index 9710a53..5053b01 100644 --- a/tests/func.sh +++ b/tests/func.sh @@ -170,7 +170,6 @@ do_setup() { dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1 # make sure udev doesn't touch mdadm --zero $targetdir/mdtest$d 2> /dev/null - [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d if [ $d -eq 7 ] then losetup /dev/loop$d $targetdir/mdtest6 # for multipath use diff --git a/tests/templates/names_template b/tests/templates/names_template new file mode 100644 index 0000000..6181bfa --- /dev/null +++ b/tests/templates/names_template @@ -0,0 +1,80 @@ +# NAME is optional. Testing with native 1.2 superblock. +function names_create() { + local DEVNAME=$1 + local NAME=$2 + local NEG_TEST=$3 + + if [[ -z "$NAME" ]]; then + mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force + else + mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force + fi + + if [[ "$NEG_TEST" == "true" ]]; then + [[ "$?" == "0" ]] && return 0 + echo "Negative verification failed" + exit 1 + fi + + if [[ "$?" != "0" ]]; then + echo "Cannot create device." + exit 1 + fi +} + +# Three properties to check: +# - devnode name +# - link in /dev/md/ (MD_DEVNAME property from --detail --export) +# - name in metadata (MD_NAME property from --detail --export)- that works only with 1.2 sb. +function names_verify() { + local DEVNODE_NAME="$1" + local WANTED_LINK="$2" + local WANTED_NAME="$3" + + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" + if [[ "$?" != "0" ]]; then + echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." + exit 1 + fi + + if [[ "$WANTED_LINK" != "empty" ]]; then + local EXPECTED="MD_DEVNAME=$WANTED_LINK" + fi + + if [[ "$RES" != "$EXPECTED" ]]; then + echo "$RES doesn't match $EXPECTED." + exit 1 + fi + + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_NAME)" + if [[ "$?" != "0" ]]; then + echo "Cannot get metadata from $dev0." + exit 1 + fi + + local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" + if [[ "$RES" != "$EXPECTED" ]]; then + echo "$RES doesn't match $EXPECTED." + exit 1 + fi +} + +# Generate ARRAYLINE for tested array. +names_make_conf() { + local UUID="$1" + local WANTED_DEVNAME="$2" + local WANTED_NAME="$3" + local CONF="$4" + + local LINE="ARRAY metadata=1.2 UUID=$UUID" + + if [[ "$WANTED_DEVNAME" != "empty" ]]; then + LINE="$LINE $WANTED_DEVNAME" + fi + + if [[ "$WANTED_NAME" != "empty" ]]; then + LINE="$LINE name=$WANTED_NAME" + fi + + echo $LINE > $CONF +} -- cgit v1.2.3