Re: [PATCH v2] vfio/ccw: Flush notoper_work before returning from reset

From: Christian Borntraeger

Date: Mon Nov 09 2026 - 14:42:31 EST




Am 09.11.26 um 15:49 schrieb Jason Gunthorpe:
On Mon, Nov 09, 2026 at 01:38:44PM +0100, Christian Borntraeger wrote:
Am 06.11.26 um 20:10 schrieb Yuho Choi:
vfio_ccw_dma_unmap() is the DMA invalidation callback, which must unpin
the pages covering the range before it returns. It calls
vfio_ccw_mdev_reset(), which raises a CLOSE event.

On the normal path fsm_close() calls cp_free() itself, so the pages are
unpinned synchronously. But if the subchannel cannot be disabled or
quiesced, fsm_close() falls through to a NOT_OPER event. Since commit
0c11f61a876e ("s390/vfio_ccw: Move cp cleanup out of not operational"),
fsm_notoper() only queues notoper_work, which is where cp_free() then
runs. That commit flushes the work in vfio_ccw_mdev_close_device() and
vfio_ccw_mdev_release_dev(), but nothing waits for it on the reset
path, so the callback returns with the pages still pinned.

Because notoper_work runs asynchronously, vfio_dma_do_unmap() can exhaust
its 10 retries before cp_free() completes, hitting BUG_ON(++retries > 10)
and taking the host down. A further CLOSE cannot help either, as both
CLOSE and OPEN are fsm_nop in the NOT_OPER state.

Does the the iommufd backend have the same problem?
iopt_unmap_iova_range() keeps calling the unmap callback and gives up with
WARN_ON(tries > 100) and -EDEADLOCK. So that path is also fixed, I
guess.

Drivers are not allowed to refuse the shootdown, it is broken if
someone has done this.

Agreed, but isnt that what the patch fixes? when CLOSE fails, vfio-ccw
currently returns from the unmap callback with the pages still pinned
and leaves the unpin to notoper_work. With the flush the pages are
unpinned before the callback returns, so the driver keeps the
contract on both backends.

> Jason