Page MenuHomeFreeBSD

bhyve: nvme: drop the completions of commands from before a reset
Needs ReviewPublic

Authored by wanpengqian_gmail.com on Fri, Oct 2, 6:24 AM.

Details

Reviewers
imp
chuck
corvink
Group Reviewers
bhyve
Summary

When the guest resets the controller (CC.EN 1 -> 0), the I/O requests
that are in flight go on in the block layer. When one of them completed
after the reset, its completion was posted through the cqid of its
submission queue, which the reset has set to 0: it went into the admin
completion queue of the controller that the guest had enabled again in
the meantime, or, with the controller still disabled, failed the
assertion in pci_nvme_cq_update().

A guest that finds a completion it did not ask for in its new admin
queue does not recover. Windows 10, which resets the controller when a
command takes longer than its timeout, stopped with
WHEA_UNCORRECTABLE_ERROR (0x124); FreeBSD panics with "NVME polled
command failed to complete within 10s".

Count the resets, note the count in each I/O request and post the
completion only if there was no reset in between. A Dataset Management
command that has more ranges to deallocate stops there as well.
CSTS.RDY still waits for the requests in flight, as before.

Signed-off-by: Wanpeng Qian <wanpengqian@gmail.com>
Sponsored by: keelos.dev

Test Plan

main (f958aa7e7), FreeBSD 16.0-CURRENT guest with -s 4,nvme,/dev/md1.nop. The backing device is slow: gnop(8) with a delay of 3 s on every read.

In the guest, reset the controller while a read is in flight:

dd if=/dev/nda0 of=/dev/null bs=4k count=1 skip=1000 &
sleep 1; nvmecontrol reset nvme0

Before: the guest does not get its controller back and panics

nvme0: Resetting controller due to a timeout.
panic: NVME polled command failed to complete within 10s.
nvme_ctrlr_identify() at nvme_ctrlr_identify+0x14e
nvme_ctrlr_start() at nvme_ctrlr_start+0xa0
nvme_ctrlr_reset_task() at nvme_ctrlr_reset_task+0xa4

After: three rounds of the same. Each time the controller comes back, the guest's driver retries the read (the dd ends after 6 s), and later reads and admin commands (nvmecontrol identify nvme0) work.

How it was found (FreeBSD 14.5): Windows 10 with its system disk on an emulated NVMe controller, backed by a zvol on a pool that was busy writing. A Dataset Management command took 9-12 s, Windows reset the controller and stopped with WHEA_UNCORRECTABLE_ERROR (0x124) soon after. With this change there, together with a time limit for Dataset Management that is not part of this review, it no longer does.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 77604
Build 74487: arc lint + arc unit