# DF-2661 — hammer2 DIO error path leaves stale `dio->bp` with `DIO_GOOD` cleared → state-machine violation, panic on concurrent accessor

* File: `sys/vfs/hammer2/hammer2_io.c` (pass-2 audit of this file)
* Root cause: `_hammer2_io_getblk()` error path (io.c:350-373 vs io.c:254)
* Severity: Medium (kernel panic / local DoS on device read error)
* Bucket: hammer2
* Related: DF-2662 (second EIO-path panic unmasked by this fix — different
  file, `hammer2_iocom.c`)

## Kernels used (all built in-guest with `make -j6 nativekernel`)

* **A (baseline)**  = stock + `inject.diff`  (build.sh; log lost to the
  mandatory post-panic `vm.sh reset with-src` — procedure identical to
  kernel B's minus `fix_b.diff`)
* **B (fix 1)**     = stock + `inject.diff` + `fix_b.diff` (build.log /
  buildB.log) — DF-2661's assert is GONE; the same storm then exposes the
  unrelated DF-2662 NULL deref (`hammer2_update_spans`)
* **C (fix 1+2)**   = kernel B source + DF-2662's `fix.diff`
  (fix_build.log / DF-2662/buildC.log)

## Media prep (once per fresh guest)

    sh /root/df2661/trigger_df2661.sh golden

512MB vn(4)-backed hammer2 volume, 40 inodes in one directory (one 64KB
DIO window), golden image materialized via `dd if=/dev/vn2` while
attached.  NEVER use `vnconfig -T` on prepared images (it is O_TRUNC).

## Run (per kernel)

    sh /root/df2661/trigger_df2661.sh 5        # ARM=1 (default): EIO storm
    ARM=0 sh /root/df2661/trigger_df2661.sh 5  # control: no EIO

## Expected / observed

* Kernel A: **panic** `assertion "dio->bp == NULL" failed in
  _hammer2_io_getblk at hammer2_io.c:264` (= stock :254 + 10 injector
  lines) — guest wedged in ddb (panic.txt, run_baseline.txt).
* Kernel B + ARM=0 control: 5/5 ROUND_SURVIVED (crash is EIO-specific).
* Kernel B + ARM=1: no dio assert anymore; crashes in DF-2662's
  `hammer2_update_spans` instead (see DF-2662 pack).
* Kernel C + ARM=1: **5/5 ROUND_SURVIVED + ALL_ROUNDS_SURVIVED, RC=0**
  (fix_run.log, run twice).
