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