# DF-2568 — hammer2_flush retry-loop NULL-deref panic

## Finding
`hammer2_flush` retry loop at `sys/vfs/hammer2/hammer2_flush.c:405` calls
`hammer2_chain_ref(info.parent)` without checking for NULL, unlike the initial
setup at :382-383 and cleanup at :434-435 which guard. When a concurrent unlink
deletes the chain's parent during the flush's unlock/relock window
(flush_core:662-665), `chain->parent` becomes NULL, and the retry's
`hammer2_chain_ref(NULL)` dereferences a NULL pointer → kernel panic.

## PoC files
- `race_flush.c` — v1: workers create+write+fsync+unlink, syncers (basic)
- `race_flush_v2.c` — v2: shared dir + rename churn
- `race_flush_v3.c` — v3: population churn + dir churn
- `race_flush_v5.c` — v5: focused fsync-vs-unlink + rename
- `race_flush_v6.c` — v6: concurrent dirtier/unlinker shared pool (PRIMARY)
- `race_flush_v7.c` — v7: 512KB files for indirect chains
- `setup.sh` — root: create vnode-backed hammer2 fs at /h2mnt
- `build.sh` — build the PoC
- `run.sh` — run the PoC as unprivileged user

## Build
```
./build.sh    # or: cc -O2 -pipe -o race_flush race_flush.c
```

## Setup (as root)
```
./setup.sh    # creates 2G vnode-backed hammer2 fs, mounts at /h2mnt, chowns /h2mnt/race to maxx
```

## Run (as unprivileged user)
```
./run.sh      # races concurrent create+write+fsync+unlink+sync on /h2mnt/race
```

Or run a specific variant:
```
cc -O2 -pipe -o race_flush_v7 race_flush_v7.c
./race_flush_v7 -d /h2mnt/race -D 12 -U 12 -s 4 -p 16 -f 512 -t 300
```

## Expected result
**On an unpatched kernel IF the race is won**: kernel panic (NULL deref in
`hammer2_chain_ref`) — `fatal trap 12: page fault while in kernel mode`,
fault address near 0.

**In practice**: The race is extremely narrow. After 45+ minutes of stress
testing with 7 PoC variants, the race was never triggered (zero "LOST CHILD"
messages with `vfs.hammer2.debug=0x40`). The code bug is real but the race
window is too narrow for userspace concurrency to hit reliably.

## Fix
See `fix.diff` — adds `if (info.parent != NULL)` guard before
`hammer2_chain_ref(info.parent)` at flush.c:405, matching the pattern at
:382-383 and :434-435.
