From 85ecc136c7bbee5abf65f07fb6d949465106f79c Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Thu, 30 Apr 2026 16:14:38 -0700 Subject: [PATCH] Add test exercising the totl recompute ioctl. Basic validation for the recompute-xattr-total ioctl through the totl-delta-inject ioctl. Takes a few different corrective actions that are plausible - simple drifted values, and a stray orphan totl. The test validates that the kmod dmesg output matches what was expected since that's our proof that repair happened, but the actual warnings are filtered from logs during test to not fail our test case otherwise. Signed-off-by: Auke Kok --- tests/funcs/filter.sh | 3 ++ tests/golden/totl-recompute | 23 ++++++++++ tests/sequence | 1 + tests/tests/totl-recompute.sh | 81 +++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 tests/golden/totl-recompute create mode 100644 tests/tests/totl-recompute.sh diff --git a/tests/funcs/filter.sh b/tests/funcs/filter.sh index 1016b8ef..6ada9c04 100644 --- a/tests/funcs/filter.sh +++ b/tests/funcs/filter.sh @@ -171,6 +171,9 @@ t_filter_dmesg() # orphan log trees reclaim is handled, not an error re="$re|scoutfs .* reclaiming orphan log trees" + # recompute-xattr-total logs every corrective delta it applies + re="$re|scoutfs .* warning: totl recompute applying delta .*" + # fencing tests force unmounts and trigger timeouts re="$re|scoutfs .* forcing unmount" re="$re|scoutfs .* reconnect timed out" diff --git a/tests/golden/totl-recompute b/tests/golden/totl-recompute new file mode 100644 index 00000000..0f90a445 --- /dev/null +++ b/tests/golden/totl-recompute @@ -0,0 +1,23 @@ +== setup three files contributing to totl 8888.0.0 +== merge baseline into fs_root +8888.0.0 = 42, 3 +== recompute on a clean baseline is a no-op +8888.0.0 = 42, 3 +== inject (+128, +2) corrupts totl 8888.0.0 +8888.0.0 = 170, 5 +== recompute restores 8888.0.0 +totl recompute applying delta total=-128 count=-2 to key 12.8888.0.0.0.0 (was total=170 count=5, recomputed total=42 count=3) +8888.0.0 = 42, 3 +== inject (-50, +1) corrupts totl 8888.0.0 again +8888.0.0 = -8, 4 +== recompute restores 8888.0.0 +totl recompute applying delta total=50 count=-1 to key 12.8888.0.0.0.0 (was total=-8 count=4, recomputed total=42 count=3) +8888.0.0 = 42, 3 +== recompute on an unused key is a no-op +8888.0.0 = 42, 3 +== inject (+7, +1) at unused key 8888.1.1 then recompute clears it +8888.0.0 = 42, 3 +8888.1.1 = 7, 1 +totl recompute applying delta total=-7 count=-1 to key 12.8888.0.1.1.0 (was total=7 count=1, recomputed total=0 count=0) +8888.0.0 = 42, 3 +== cleanup diff --git a/tests/sequence b/tests/sequence index d2ac6a0d..2e613719 100644 --- a/tests/sequence +++ b/tests/sequence @@ -30,6 +30,7 @@ basic-xattr-indx.sh quota.sh totl-merge-read.sh totl-delta-inject.sh +totl-recompute.sh lock-refleak.sh lock-shrink-consistency.sh lock-shrink-read-race.sh diff --git a/tests/tests/totl-recompute.sh b/tests/tests/totl-recompute.sh new file mode 100644 index 00000000..a12abbb8 --- /dev/null +++ b/tests/tests/totl-recompute.sh @@ -0,0 +1,81 @@ +# +# Exercise scoutfs recompute-xattr-total. Uses totl-delta-inject(1) to seed +# corruption. +# + +t_require_commands setfattr scoutfs sync rm touch totl-delta-inject + +# force a log merge then read-xattr-totals filtered to our own keys +read_totals() +{ + t_force_log_merge + sync + echo 1 > $(t_debugfs_path)/drop_weak_item_cache + scoutfs read-xattr-totals -p "$T_M0" | \ + grep -E '^8888\.' || true +} + +# Print recompute warnings emitted since the last snapshot, with the +# volatile timestamp/fsid/rid prefix stripped, for golden comparison. +DMESG_SNAP="$T_TMPDIR/dmesg.recompute.snap" +dmesg > "$DMESG_SNAP" + +recompute_warn() +{ + local cur="$T_TMPDIR/dmesg.recompute.cur" + + dmesg > "$cur" + diff "$DMESG_SNAP" "$cur" | \ + sed -n 's/^> \[ *[0-9.]\+\] scoutfs [^ ]\+ warning: \(totl recompute applying delta .*\)$/\1/p' + mv "$cur" "$DMESG_SNAP" +} + +echo "== setup three files contributing to totl 8888.0.0" +touch "$T_D0/f1" "$T_D0/f2" "$T_D0/f3" +setfattr -n scoutfs.totl.inj.8888.0.0 -v 2 "$T_D0/f1" +setfattr -n scoutfs.totl.inj.8888.0.0 -v 8 "$T_D0/f2" +setfattr -n scoutfs.totl.inj.8888.0.0 -v 32 "$T_D0/f3" + +echo "== merge baseline into fs_root" +read_totals + +echo "== recompute on a clean baseline is a no-op" +scoutfs recompute-xattr-total -p "$T_M0" 8888.0.0 +recompute_warn +read_totals + +echo "== inject (+128, +2) corrupts totl 8888.0.0" +totl-delta-inject "$T_M0" 8888.0.0 128 2 +read_totals + +echo "== recompute restores 8888.0.0" +scoutfs recompute-xattr-total -p "$T_M0" 8888.0.0 +recompute_warn +read_totals + +echo "== inject (-50, +1) corrupts totl 8888.0.0 again" +totl-delta-inject "$T_M0" 8888.0.0 -50 1 +read_totals + +echo "== recompute restores 8888.0.0" +scoutfs recompute-xattr-total -p "$T_M0" 8888.0.0 +recompute_warn +read_totals + +echo "== recompute on an unused key is a no-op" +scoutfs recompute-xattr-total -p "$T_M0" 8888.1.1 +recompute_warn +read_totals + +echo "== inject (+7, +1) at unused key 8888.1.1 then recompute clears it" +totl-delta-inject "$T_M0" 8888.1.1 7 1 +read_totals +scoutfs recompute-xattr-total -p "$T_M0" 8888.1.1 +recompute_warn +read_totals + +echo "== cleanup" +rm -f "$T_D0/f1" "$T_D0/f2" "$T_D0/f3" +read_totals + +t_pass