Re: [RFC PATCH v1 01/17] nvme-multipath: retarget failedover bios from requeue work
Hannes Reinecke <[email protected]> Mon, 13 Jul 2026 11:29:35 +0200
| Newsgroups | org.kernel.vger.linux-bcache,dev.linux.lists.dm-devel,org.infradead.lists.linux-nvme,org.kernel.vger.cgroups,org.kernel.vger.linux-block |
|---|---|
| Message-ID | <[email protected]> |
On 7/4/26 9:51 PM, Yu Kuai wrote: > From: Yu Kuai <[email protected]> > > bio_set_dev() is about to become explicitly sleepable because it can > associate the bio with a blkg for the destination queue. NVMe failover > can run from request completion context, and nvme_failover_req() also holds > head->requeue_lock with interrupts disabled while it steals bios from the > failed request. Calling bio_set_dev() there is not safe once the helper is > allowed to sleep. > > The requeue lock only protects head->requeue_list. Keep the list > manipulation under that lock, but defer retargeting to nvme_requeue_work(), > which already drains the list from process context before resubmitting each > bio. The bios remain private to the requeue list until the worker pops > them, so moving the device switch there preserves the existing retry flow > while avoiding a sleepable helper in completion context. > > Signed-off-by: Yu Kuai <[email protected]> > --- > drivers/nvme/host/multipath.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c > index 9b9a657fa330..76baa180ae1c 100644 > --- a/drivers/nvme/host/multipath.c > +++ b/drivers/nvme/host/multipath.c > @@ -149,7 +149,6 @@ void nvme_failover_req(struct request *req) > struct nvme_ns *ns = req->q->queuedata; > u16 status = nvme_req(req)->status & NVME_SCT_SC_MASK; > unsigned long flags; > - struct bio *bio; > > nvme_mpath_clear_current_path(ns); > atomic_long_inc(&ns->failover); > @@ -165,8 +164,6 @@ void nvme_failover_req(struct request *req) > } > > spin_lock_irqsave(&ns->head->requeue_lock, flags); > - for (bio = req->bio; bio; bio = bio->bi_next) > - bio_set_dev(bio, ns->head->disk->part0); If you remove this the original device remains being referenced by the bio, so there might be a chance of some accidentally referencing the (now invalid) bdev. I think it might be better if you were set it to NULL here, to signal that this bio currently has no bdev associated. > blk_steal_bios(&ns->head->requeue_list, req); > spin_unlock_irqrestore(&ns->head->requeue_lock, flags); > > @@ -684,6 +681,7 @@ static void nvme_requeue_work(struct work_struct *work) > next = bio->bi_next; > bio->bi_next = NULL; > > + bio_set_dev(bio, head->disk->part0); > submit_bio_noacct(bio); > } > } Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect [email protected] +49 911 74053 688 SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich