NVDIMM Device and Persistent Memory development
 help / color / mirror / Atom feed
* [ndctl PATCH] test/btt-stress.sh: add stress test for BTT lane race
@ 2026-04-24 23:36 Alison Schofield
  2026-06-03 19:04 ` Verma, Vishal L
  2026-06-30 17:40 ` Alison Schofield
  0 siblings, 2 replies; 4+ messages in thread
From: Alison Schofield @ 2026-04-24 23:36 UTC (permalink / raw)
  To: nvdimm; +Cc: Alison Schofield

The btt-check unit test exposed data mismatches during BTT I/O in a
CI environment, indicating a race in lane acquisition that can lead
to silent data corruption. The failure was not reliably reproduced
under typical test conditions.

Add a targeted stress test that repeatedly writes, reads, and verifies
data on a BTT namespace while background readers contend for BTT lanes
and CPU loops increase preemption pressure.

The test reproduces the race on an unfixed kernel and passes with the
lane ownership fix applied.

Assisted-By: Claude Sonnet 4.5
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
 test/btt-stress.sh | 111 +++++++++++++++++++++++++++++++++++++++++++++
 test/meson.build   |   2 +
 2 files changed, 113 insertions(+)
 create mode 100755 test/btt-stress.sh

diff --git a/test/btt-stress.sh b/test/btt-stress.sh
new file mode 100755
index 000000000000..c1892f536d75
--- /dev/null
+++ b/test/btt-stress.sh
@@ -0,0 +1,111 @@
+#!/bin/bash -E
+# SPDX-License-Identifier: GPL-2.0
+
+dev=""
+mode=""
+size=""
+sector_size=""
+blockdev=""
+rc=77
+
+. $(dirname $0)/common
+
+trap 'err $LINENO' ERR
+
+check_min_kver "7.1" || do_skip "known BTT lane race before fix"
+
+# Stress BTT I/O under contention to exercise lane acquisition races.
+# Background readers contend for lanes while CPU loops increase
+# preemption pressure.
+
+create() {
+	json=$($NDCTL create-namespace -b "$NFIT_TEST_BUS0" -t pmem -m sector)
+	rc=2
+	eval "$(echo "$json" | json2var)"
+	[ -n "$dev" ] || err "$LINENO"
+	[ "$mode" = "sector" ] || err "$LINENO"
+	[ -n "$size" ] || err "$LINENO"
+	[ -n "$sector_size" ] || err "$LINENO"
+	[ -n "$blockdev" ] || err "$LINENO"
+	[ "$size" -gt 0 ] || err "$LINENO"
+}
+
+# Start background workers:
+#   - readers contend for lanes
+#   - CPU loops increase preemption
+start_bg_workers() {
+	local ncpus
+	ncpus=$(nproc)
+	local nworkers=$((ncpus / 2))
+
+	# Ensure at least one worker, cap to limit runtime noise
+	[ $nworkers -lt 1 ] && nworkers=1
+	[ $nworkers -gt 8 ] && nworkers=8
+
+	BG_PIDS=()
+	local i
+	for i in $(seq 1 $nworkers); do
+		# Reader: contends for lanes (use O_DIRECT to avoid page cache)
+		(while :; do
+			dd if=/dev/"$blockdev" of=/dev/null \
+				bs="$sector_size" count=256 \
+				iflag=direct >/dev/null 2>&1 || true
+		done) &
+		BG_PIDS+=($!)
+
+		# CPU hog: increase preemption
+		(while :; do :; done) &
+		BG_PIDS+=($!)
+	done
+	echo "started $nworkers readers + $nworkers CPU hogs"
+}
+
+stop_bg_workers() {
+	local pid
+	for pid in "${BG_PIDS[@]}"; do
+		kill "$pid" 2>/dev/null || true
+	done
+	wait "${BG_PIDS[@]}" 2>/dev/null || true
+	BG_PIDS=()
+}
+
+# Write, read, and verify data
+do_io_verify() {
+	dd if=/dev/urandom of=test-bin \
+		bs="$sector_size" count=$((size / sector_size)) >/dev/null 2>&1
+	dd if=test-bin of=/dev/"$blockdev" \
+		bs="$sector_size" count=$((size / sector_size)) >/dev/null 2>&1
+	dd if=/dev/"$blockdev" of=test-bin-read \
+		bs="$sector_size" count=$((size / sector_size)) >/dev/null 2>&1
+	diff test-bin test-bin-read
+	rm -f test-bin*
+}
+
+# Run verification under contention
+test_io_stress() {
+	local iterations=${1:-20}
+	echo "=== ${FUNCNAME[0]} ($iterations iterations) ==="
+
+	start_bg_workers
+	trap 'stop_bg_workers; err $LINENO' ERR
+
+	local i
+	for i in $(seq 1 "$iterations"); do
+		echo "--- iteration $i/$iterations ---"
+		do_io_verify
+	done
+
+	stop_bg_workers
+	trap 'err $LINENO' ERR
+}
+
+modprobe nfit_test
+rc=1
+reset && create
+
+# 30 iterations balances runtime and reproduction probability
+test_io_stress 30
+
+reset
+_cleanup
+exit 0
diff --git a/test/meson.build b/test/meson.build
index e0e2193bfd51..ee6a18762a17 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -150,6 +150,7 @@ sector_mode = find_program('sector-mode.sh')
 inject_error = find_program('inject-error.sh')
 btt_errors = find_program('btt-errors.sh')
 btt_pad_compat = find_program('btt-pad-compat.sh')
+btt_stress = find_program('btt-stress.sh')
 firmware_update = find_program('firmware-update.sh')
 rescan_partitions = find_program('rescan-partitions.sh')
 inject_smart = find_program('inject-smart.sh')
@@ -185,6 +186,7 @@ tests = [
   [ 'sector-mode.sh',         sector_mode,        'ndctl' ],
   [ 'inject-error.sh',        inject_error,	  'ndctl' ],
   [ 'btt-errors.sh',          btt_errors,	  'ndctl' ],
+  [ 'btt-stress.sh',          btt_stress,	  'ndctl' ],
   [ 'hugetlb',                hugetlb,		  'ndctl' ],
   [ 'btt-pad-compat.sh',      btt_pad_compat,	  'ndctl' ],
   [ 'ack-shutdown-count-set', ack_shutdown_count, 'ndctl' ],
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-30 17:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-24 23:36 [ndctl PATCH] test/btt-stress.sh: add stress test for BTT lane race Alison Schofield
2026-06-03 19:04 ` Verma, Vishal L
2026-06-03 23:22   ` Alison Schofield
2026-06-30 17:40 ` Alison Schofield

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox