Files
erofs-freebsd-out-tree/tests/TC127-memory-pressure.md
T
2026-08-13 10:44:59 +02:00

3.8 KiB

Test Case: Controlled Memory Pressure

Test ID: TC127-memory-pressure
Category: Boundary & Stress
Priority: High
Regression: None

Objective

Verify correct EROFS reads while three synchronized FreeBSD processes touch memory up to per-process RCTL virtual-memory denial, then prove allocation failure, release, recovery, PID exit, and read integrity.

Preconditions

  • Complete G7-MANUAL-SETUP.md.
  • sysctl -n kern.racct.enable must print 1. Record an ENV result instead of inventing pressure if this loader facility cannot be enabled.
  • Use rctl vmemoryuse:deny; do not use the invalid jail -m 256M command.

Manual Steps

G7=/root/repo22-g7
FIX=$G7/fixtures
SRC=$FIX/sources/workloads/pressure/pressure.bin
IMAGE=$FIX/images/workloads.erofs
MNT=/mnt/repo22-g7-tc127
E=$G7/evidence/TC127
mkdir -p "$MNT" "$E"
test "$(sysctl -n kern.racct.enable)" -eq 1
sysctl kern.racct.enable | tee "$E/racct.txt"
rctl | tee "$E/rctl-before.txt"
vmstat -H 1 5 | tee "$E/vmstat-before.txt"
unit=$(mdconfig -a -t vnode -f "$IMAGE")
mount -t erofs -o ro "/dev/$unit" "$MNT"
: > "$E/pids.tsv"
index=1
while [ "$index" -le 3 ]; do
  rm -f "$E/go-$index" "$E/stop-$index" "$E/pressure-$index.log"
  "$G7/g7_probe" pressure "$E/go-$index" "$E/stop-$index" 1024 \
    > "$E/pressure-$index.log" 2>&1 &
  pid=$!
  printf '%s\t%s\n' "$index" "$pid" >> "$E/pids.tsv"
  index=$((index + 1))
done
attempt=0
while [ "$attempt" -lt 30 ]; do
  ready=$(grep -l '^state=waiting ' "$E"/pressure-*.log 2>/dev/null \
    | wc -l | tr -d ' ')
  test "$ready" -eq 3 && break
  sleep 1
  attempt=$((attempt + 1))
done
test "$ready" -eq 3
: > "$E/rctl-rules.txt"
while IFS="$(printf '\t')" read -r worker pid; do
  rctl -a "process:$pid:vmemoryuse:deny=640M"
  rctl -l "process:$pid" >> "$E/rctl-rules.txt"
  touch "$E/go-$worker"
done < "$E/pids.tsv"
attempt=0
while [ "$attempt" -lt 120 ]; do
  holding=$(grep -l '^state=holding .*allocation_failure=ENOMEM ' \
    "$E"/pressure-*.log 2>/dev/null | wc -l | tr -d ' ')
  test "$holding" -eq 3 && break
  sleep 1
  attempt=$((attempt + 1))
done
test "$holding" -eq 3
vmstat -H 1 10 | tee "$E/vmstat-pressure.txt"
rctl -hu process:$(awk 'NR == 1 { print $2 }' "$E/pids.tsv") \
  | tee "$E/rctl-utilization.txt"
source_hash=$(sha256 -q "$SRC")
target_hash=$(sha256 -q "$MNT/pressure/pressure.bin")
printf 'source=%s\ntarget=%s\n' "$source_hash" "$target_hash" \
  | tee "$E/hashes.txt"
test "$source_hash" = "$target_hash"
cmp "$SRC" "$MNT/pressure/pressure.bin"
while IFS="$(printf '\t')" read -r worker pid; do
  touch "$E/stop-$worker"
done < "$E/pids.tsv"
failed=0
: > "$E/waits.tsv"
while IFS="$(printf '\t')" read -r worker pid; do
  wait "$pid"
  rc=$?
  printf '%s\t%s\t%s\n' "$worker" "$pid" "$rc" >> "$E/waits.tsv"
  test "$rc" -eq 0 || failed=$((failed + 1))
  rctl -r "process:$pid:vmemoryuse:deny=640M" 2>/dev/null || true
done < "$E/pids.tsv"
test "$failed" -eq 0
grep '^state=released .*recovery=ok exit=0$' "$E"/pressure-*.log
vmstat -H 1 10 | tee "$E/vmstat-after.txt"
rctl | tee "$E/rctl-after.txt"
rm -f "$E"/go-* "$E"/stop-*
cat "$E/pids.tsv" "$E/waits.tsv" "$E"/pressure-*.log
umount "$MNT"
mdconfig -d -u "${unit#md}"
test -z "$(mount -p | awk -v m="$MNT" '$2 == m { print }')"
test -z "$(mdconfig -l | tr ' ' '\n' | grep -x "$unit")"

PASS Gate

  • RACCT/RCTL availability and before/pressure/after vmstat are recorded.
  • Three persisted PIDs each report allocation_failure=ENOMEM, later report exact released bytes and recovery=ok, and exit 0 when waited.
  • The mounted 96 MiB file SHA256 and full bytes match the source while pressure is held.
  • G7 RCTL rules, synchronization files, mount, and provider are removed.

Different page counts or allocation totals are recording-only. Read mismatch, panic, hang, unreclaimed process, or unexpected kernel error is KFAIL.