[PATCH] nvme: honor the volatile write cache enable state
Erwan Velu
e.velu at criteo.com
Fri Oct 16 21:25:43 PDT 2026
[...]
> Unfortunately, no: there are contradicting statements here.
Hi Keith,
Sorry for the confusion, my previous replies were wrong and contradicted
the commit message. Let me restate it with new measurements.
To make sure the numbers are relevant, I switched to the latest nvme
branch, nvme-7.4 (2e8e30b3cf9f), and re-ran all the tests from scratch,
with and without the patch on top of it, on the same drive (Kioxia
CD6-V, NVMe 1.4, VWC 0x5, WCE cleared by default).
Both rows of each job in the commit message table were measured with
WCE cleared; only the kernel differs. Without the patch, WCE is ignored
and the namespace is exposed in write-back mode, so one Flush is sent
per fsync. With the patch, the namespace is in write-through mode and no
Flush is sent.
To answer your question, I measured the Flush latency at the driver
level, between the nvme_setup_cmd and nvme_complete_rq tracepoints:
- passthrough: 2000 "nvme flush" sent directly to the device
- fio: 4k randwrite, io_uring, direct, QD1, fsync=1, 10s
kernel | WCE | mode | passthrough | fio: Flush | fio: fsync | IOPS
| | | Flush avg | avg (drv) | avg (fio) |
--------+-----+---------+-------------+------------+------------+------
nvme-7.4| 0 | back | 194.8us | 214.6us | 236.1us | 3917
patched | 0 | through | 194.2us | (none) | 5.7us | 44433
patched | 1 | back | 194.2us | 219.7us | 237.1us | 3916
So:
- The block layer flush handling is not the reason: without the patch,
the device accounts for ~215us of the ~236us fsync, the rest of the
stack for ~21us.
- The drive spends ~194us on a Flush whether the volatile write cache
is enabled or not. It does not short-circuit the Flush when WCE is
cleared, although the spec says it has no effect in that case.
- Without the patch, WCE cleared therefore performs exactly like the
volatile write cache enabled (3917 vs 3916 IOPS), while the patched
kernel skips the Flush entirely (44433 IOPS).
The slow no-op Flush is a firmware behavior, but the kernel should not
send it in the first place when WCE is cleared, which is what the patch
does.
I also re-ran the commit message benchmark on nvme-7.4, WCE cleared in
both cases (fio 4k randwrite, fsync=1, 30s):
job | kernel | IOPS | fsync avg | flushes | gain
----------------------+----------+--------+-----------+---------+------
psync buffered, QD1 | nvme-7.4 | 3917 | 249.2us | 117506 |
| patched | 48227 | 15.7us | 0 | x12.3
----------------------+----------+--------+-----------+---------+------
io_uring direct, QD1 | nvme-7.4 | 3888 | 238.2us | 116636 |
| patched | 42580 | 5.5us | 0 | x11.0
----------------------+----------+--------+-----------+---------+------
io_uring direct, QD32 | nvme-7.4 | 5674 | 5514.1us | 117774 |
| patched | 140090 | 107.1us | 0 | x24.7
If you think it makes the commit message clearer, I can send a v2 with
these numbers, the kernel anitly, and the driver level Flush latency above.
Thanks,
Erwan
More information about the Linux-nvme
mailing list