# DF-4639 — ips(4): `debug.ips.ignore_flush_cmd` polarity inverted — adapter cache-flush silently dropped on DEFAULT configuration

**File:** `sys/dev/raid/ips/ips_commands.c:195-220` (supporting: `:35-40`, `:249-252`)
**Severity:** Medium (data integrity on default config) · **Confidence:** certain
**Class:** CWE-670 (Always-Incorrect Control Flow Implementation)

## Build

```sh
sh build.sh          # cc -O2 -Wall -o /tmp/flush_invert_harness flush_invert_harness.c
```

## Run

```sh
sh run.sh            # uname, live sysctl default, harness as unprivileged user
```

## Expected output (bug present)

```
debug.ips.ignore_flush_cmd: 0
DEFAULT (flag=0):   flag=0 -> adapter_cmds_issued=0 last_opcode=0x00 bio_finished=1(no error)
DEBUG SET (flag=1): flag=1 -> adapter_cmds_issued=1 last_opcode=0x0a bio_finished=0(no error)
RESULT: INVERTED — with the DEFAULT value the real adapter cache-flush ...
harness exit code: 42
```

## What it proves

1. **Live guest kernel** (ips driver compiled into `X86_64_GENERIC`): the
   sysctl exists and its default is `0` (`run.log` line 2; source
   `ips_commands.c:35-36` `TUNABLE_INT(..., &ips_debug_ignore_flush_cmd)` —
   static, i.e. zero-initialized).
2. **The branch** (`ips_commands.c:202`): `if (!ips_debug_ignore_flush_cmd)`
   is taken at the DEFAULT — it frees the command slot, completes the bio
   with **no error**, and returns **without** ever building/issuing
   `IPS_CACHE_FLUSH_CMD` to the adapter. Setting the debug flag to 1 — which
   per the sysctl's own description
   (`"Do not issue IPS_CACHE_FLUSH_CMD on BUF_CMD_FLUSH"`,
   `ips_commands.c:40`) should SUPPRESS the command — instead issues it.

## Impact

Every `BUF_CMD_FLUSH` bio on an ips disk (fsync(2)/close-time flush on the
raw device, filesystem metadata flushes, unmount flush) is reported complete
while the ServeRAID adapter's volatile write cache is never told to flush.
After fsync() returns, the just-synced data can still be lost on power
failure — the durability contract of fsync is silently violated on a stock
kernel. (The separate shutdown-path flush `ips_flush_cache()`,
`ips_commands.c:476-493`, does issue the real command, so the damage window
is "flush returned → next real flush/shutdown".)

## Fix

`fix.diff` — invert the condition so the debug knob does what it documents
(skip the command only when SET). `verdict.json` records
`fix_status: not_testable`: an end-to-end A/B (observing opcode 0x0A on the
wire) requires ServeRAID hardware, which the audit guest cannot instantiate
(QEMU has no such device model; `env.txt`).
