#!/usr/bin/env bash
set -euo pipefail

VM=${1:-rocky-9-bob}
NUM_FILES=${2:-50000}
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

bh_count() {
    incus exec "$VM" -- awk '/buffer_head/{print $2}' /proc/slabinfo
}

echo "=== buffer_head leak test ==="
echo "  VM: $VM"
echo "  Files: $NUM_FILES"
echo ""

# Step 0: Clean baseline (before Lustre)
incus exec "$VM" -- bash -c 'echo 3 > /proc/sys/vm/drop_caches'
sleep 1
BH0=$(bh_count)
echo "Step 0: baseline (no Lustre)          buffer_head = $BH0"

# Step 1: Setup Lustre
bash "$SCRIPT_DIR/setup-lustre.sh" "$VM" > /dev/null 2>&1
incus exec "$VM" -- bash -c 'echo 3 > /proc/sys/vm/drop_caches'
sleep 1
BH1=$(bh_count)
echo "Step 1: after mount + drop_caches     buffer_head = $BH1"

# Step 2: Create files
incus exec "$VM" -- bash -c "
    mkdir -p /mnt/lustre/leak_test
    seq 1 $NUM_FILES | xargs -P8 -I{} touch /mnt/lustre/leak_test/file_{}
"
incus exec "$VM" -- sync
incus exec "$VM" -- bash -c 'echo 3 > /proc/sys/vm/drop_caches'
sleep 1
BH2=$(bh_count)
echo "Step 2: after create + drop_caches    buffer_head = $BH2"

# Step 3: Delete files
incus exec "$VM" -- rm -rf /mnt/lustre/leak_test
incus exec "$VM" -- sync
sleep 3
incus exec "$VM" -- bash -c 'echo 3 > /proc/sys/vm/drop_caches'
sleep 1
BH3=$(bh_count)
echo "Step 3: after delete + drop_caches    buffer_head = $BH3"

# Step 4: Unmount all (single command to avoid timeout between calls)
echo "  unmounting (this may take a while)..."
incus exec "$VM" -- bash -c '
    umount /mnt/lustre 2>/dev/null
    umount /mnt/ost1 2>/dev/null
    umount /mnt/ost0 2>/dev/null
    umount /mnt/mdt1 2>/dev/null
    umount /mnt/mdt0 2>/dev/null
    echo 3 > /proc/sys/vm/drop_caches
'
sleep 1
BH4=$(bh_count)
echo "Step 4: after umount + drop_caches    buffer_head = $BH4"

# Step 5: rmmod
incus exec "$VM" -- bash -c '
    lustre_rmmod 2>/dev/null
    rmmod ldiskfs 2>/dev/null
    rmmod lnet 2>/dev/null
    rmmod libcfs 2>/dev/null
    echo 3 > /proc/sys/vm/drop_caches
' || true
sleep 1
BH5=$(bh_count)
echo "Step 5: after rmmod + drop_caches     buffer_head = $BH5"

echo ""
echo "=== Summary ==="
echo "  baseline (no Lustre):  $BH0"
echo "  after mount:           $BH1"
echo "  after create:          $BH2"
echo "  after delete:          $BH3  (leak = delete triggered ext4_xattr_inode_dec_ref_all)"
echo "  after umount:          $BH4  (leaked refcounts prevent page reclaim)"
echo "  after rmmod:           $BH5"
echo ""
LEAKED=$((BH5 - BH0))
echo "  net leak (rmmod - baseline): $LEAKED buffer_heads (~$((LEAKED * 104)) bytes)"
