Re: [PATCH] nvme: bound the freeze drain in passthrough commands

From: Keith Busch

Date: Thu Jul 09 2026 - 14:19:21 EST


On Tue, Jun 23, 2026 at 06:28:49PM -0400, Chao S wrote:
> Timeout fires, abort is accepted, reset starts, reset reaches the
> "IO queues lost" branch (drivers/nvme/host/pci.c). Then nvme_reset_work
> itself blocks at
>
> nvme_mark_namespaces_dead -> blk_mark_disk_dead -> blk_report_disk_dead
> -> bdev_mark_dead(bdev, true) -> sync_blockdev -> folio_wait_writeback
>
> i.e. the unconditional sync_blockdev in bdev_mark_dead's bare-bdev
> else-branch (block/bdev.c) is itself waiting on the writeback that the
> reset was supposed to drain.

But sync_blockdev is *not* unconditional. It's conditional on this not
being a surprise removal, and blk_mark_disk_dead() is considered a
surprise, so I am not sure you've identified the right sequence.

> So in this report, the IO timeout did its job, but the reset that the
> timeout kicks off cannot complete, and nvme_passthru_start (which is
> already in nvme_wait_freeze at this point) has no way to back out.

I guess what may have happened is that the timeout handler requeued the
IO on a quiesced queue so it does reach frozen state. Just move the
unquiesce to before the call to nvme_mark_namespaces_dead(). But I still
don't think it should be needed because nvme_mark_namespaces_dead()
shouldn't block.

> 1. The reset path has several ways to fail to drain in
> nvme_io_timeout: abort can be rejected, the admin tag for abort
> can be unavailable, the controller can be wedged before abort
> lands, an in-progress reset can outlast nvme_io_timeout, or (as
> here) reset itself can block. Each leaves nvme_passthru_start
> waiting forever, holding ctrl->scan_lock + subsys->lock + every
> namespace's freeze ref, which then fans out on bd_disk->open_mutex
> via any concurrent bdev_open/release or BLKRRPART.

No, that's not what happens.

If abort fails, then the command times out a 2nd time, then we escalate
to reset.

If we can't get an abort tag, then that means an abort is in progress.
If it doesn't completely timely, then we escalate to reset.

> 2. The same pattern is already established in the tree. pci shutdown
> (drivers/nvme/host/pci.c), nvme-tcp reset, nvme-rdma reset,
> nvme-apple, and Daniel Wagner's 2021 nvme-fc series
> (20210818120530.130501-1-dwagner@xxxxxxx) all use
> nvme_wait_freeze_timeout(NVME_IO_TIMEOUT) for exactly this reason.
> nvme_passthru_start is the only userspace-reachable caller still
> on the unbounded variant.

Those are for entirely different cases where we're in the last line of
recovery and have to guarantee forward progress.