#!/bin/sh
# DF-4819 structural verification: the i915 GEM shrinker can never run in the
# DragonFly port because (1) register_shrinker does not exist anywhere in the
# DFly DRM linux-compat shim, (2) the i915 registration call sites are
# compiled out with #if 0, (3) count/scan bodies are #if 0 stubs returning 0,
# and (4) no VM-pressure event exists that could reach them (vm_lowmem is
# registered by ttm_page_alloc but never EVENTHANDLER_INVOKE'd anywhere).
#
# Usage:
#   ./check_shrinker_wiring.sh <path-to-sys-tree>          # static proof (host)
#   ./check_shrinker_wiring.sh --module <i915.ko>          # binary proof (guest)
set -u

fail=0
ok()   { printf 'PASS  %s\n' "$1"; }
bad()  { printf 'FAIL* %s\n' "$1"; fail=1; }

if [ "${1:-}" = "--module" ]; then
    KO="${2:?usage: $0 --module <i915.ko>}"
    echo "== binary check against $KO =="
    # The compiled module must NOT reference any shrinker registration symbol
    if nm "$KO" 2>/dev/null | grep -qE 'register_shrinker'; then
        bad "module references register_shrinker (unexpected)"
    else
        ok "module has NO register_shrinker reference -> nothing registers the shrinker"
    fi
    # count/scan must be local (lowercase) stubs: bodies are #if 0, never called
    if nm "$KO" 2>/dev/null | grep -qE ' [tT] i915_gem_shrinker_count'; then
        nm "$KO" | grep -E ' [tT] i915_gem_shrinker_(count|scan)'
    fi
    if nm "$KO" 2>/dev/null | grep -qE ' t i915_gem_shrinker_(count|scan)'; then
        ok "i915_gem_shrinker_count/scan are static stubs (t), unreachable from reclaim"
    else
        bad "count/scan unexpectedly exported/registered"
    fi
    exit $fail
fi

SYS="${1:?usage: $0 <sys-tree> | --module <i915.ko>}"
SH="$SYS/dev/drm/include/linux/shrinker.h"
DR="$SYS/dev/drm/i915/i915_gem_shrinker.c"

echo "== static check against $SYS =="

[ -f "$SH" ] || { bad "missing shim $SH"; exit 1; }
if grep -q 'register_shrinker' "$SH"; then
    bad "shim declares register_shrinker (unexpected)"
else
    ok "linux/shrinker.h shim has NO register_shrinker (struct-only: $(grep -c 'struct shrinker' "$SH") decl(s))"
fi

if grep -q 'register_oom_notifier\|register_vmap_purge_notifier' "$SH"; then
    bad "notifier registration present"
else
    ok "no OOM/vmap notifier registration exists in the shim either"
fi

# registration block must be dead code
awk '/i915_gem_shrinker_register/,/^}/' "$DR" | grep -A3 '#if 0' | grep -q 'register_shrinker' \
    && ok "i915 registration of shrinker/oom/vmap notifiers is #if 0'd out" \
    || bad "registration appears live"

# count/scan bodies must be #if 0 stubs returning 0
awk '/i915_gem_shrinker_count/,/^}/' "$DR" | grep -q '#if 0' \
    && ok "i915_gem_shrinker_count body is #if 0 (returns 0)" \
    || bad "count body live"
awk '/i915_gem_shrinker_scan/,/^}/' "$DR" | grep -q '#if 0' \
    && ok "i915_gem_shrinker_scan body is #if 0 (returns 0)" \
    || bad "scan body live"

# nothing in the whole kernel ever fires vm_lowmem
n=$(grep -rn 'EVENTHANDLER_INVOKE(vm_lowmem' "$SYS" 2>/dev/null | wc -l | tr -d ' ')
if [ "$n" = "0" ]; then
    ok "vm_lowmem is never EVENTHANDLER_INVOKE'd anywhere in sys/ (0 sites)"
else
    bad "vm_lowmem invoked at $n site(s)"
fi

# live callers of i915_gem_shrink are explicit only (get_pages failure paths,
# suspend/hibernate) — never global reclaim
echo "note: live i915_gem_shrink callers (explicit only):"
grep -rn 'i915_gem_shrink(' "$SYS/dev/drm/i915" --include='*.c' | grep -v i915_gem_shrinker.c | sed 's/^/      /'

exit $fail
