Files
erofs-freebsd-out-tree/tests/TC127-memory-pressure.md
T
2026-08-18 09:20:44 +02:00

115 lines
3.8 KiB
Markdown

# 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
```sh
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.