[PATCH 3/5] btrfs/282: dmdelay scrub I/O to fix intermittent failures

David Disseldorp
2023-12-07T07:21:14Z

btrfs/282 can fail intermittently if scrub completes quickly (e.g. atop
a RAM backed scratch device):
- if under one second, the reported scrub duration metric may be rounded
down to zero, which results in a "Rate: 0/s" metric
+ I have a btrfs-progs patch to address this confusing Rate reporting
- I've also observed one second scrub durations fail intermittently,
presumably because scheduling jitter doesn't allow throttling to take
effect

Avoid these intermittent failures by injecting a 100ms delay to device
read I/Os using dm-delay.

Signed-off-by: David Disseldorp <ddiss@suse.de>
---
tests/btrfs/282 | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/tests/btrfs/282 b/tests/btrfs/282
index 66d14f82..f9e22e12 100755
--- a/tests/btrfs/282
+++ b/tests/btrfs/282
@@ -10,6 +10,15 @@
_begin_fstest auto scrub

. ./common/filter
+. ./common/dmdelay
+
+_cleanup()
+{
+ cd /
+ rm -f $tmp.*
+ _scratch_unmount > /dev/null 2>&1
+ _cleanup_delay > /dev/null 2>&1
+}

# real QA test starts here
_supported_fs btrfs
@@ -18,6 +27,7 @@ _wants_kernel_commit eb3b50536642 \

# We want at least 5G for the scratch device.
_require_scratch_size $(( 5 * 1024 * 1024))
+_require_dm_target delay

# Make sure we can create scrub progress data file
if [ -e /var/lib/btrfs ]; then
@@ -27,7 +37,8 @@ else
fi

_scratch_mkfs >> $seqres.full 2>&1
-_scratch_mount
+_init_delay
+_mount_delay

uuid=$(findmnt -n -o UUID $SCRATCH_MNT)

@@ -45,6 +56,10 @@ $XFS_IO_PROG -f -c "pwrite -i /dev/urandom 0 2G" $SCRATCH_MNT/file | _filter_xfs
# Writeback above data, as scrub only verify the committed data.
sync

+# 100ms read I/O delay, so that the scrub doesn't complete too quickly
+bs=$(blockdev --getsz $SCRATCH_DEV)
+_load_delay_table "0 $bs delay $SCRATCH_DEV 0 100 $SCRATCH_DEV 0 0"
+
# The first scrub, mostly to grab the speed of the scrub.
$BTRFS_UTIL_PROG scrub start -B $SCRATCH_MNT >> $seqres.full

@@ -70,7 +85,8 @@ if [ -z "$init_speed" ]; then
fi

# Cycle mount to drop any possible cache.
-_scratch_cycle_mount
+_unmount_delay
+_mount_delay

target_speed=$(( $init_speed / 2 ))
echo "$target_speed" > "${devinfo_dir}/scrub_speed_max"
--
2.35.3