summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Busch <kbusch@kernel.org>2025-06-11 07:50:47 +0300
committerChristoph Hellwig <hch@lst.de>2025-06-26 14:04:35 +0300
commitdd2c18548964ae7ad48d208a765d909cd35448a1 (patch)
treedc7166defe73166fbf93139d533b89a68c312040
parent4c8a951787ffc4b61a547db9866196104971b5fd (diff)
downloadlinux-dd2c18548964ae7ad48d208a765d909cd35448a1.tar.xz
nvme: reset delayed remove_work after reconnect
The remove_work will proceed with permanently disconnecting on the initial final path failure if the head shows no paths after the delay. If a new path connects while the remove_work is pending, and if that new path happens to disconnect before that remove_work executes, the delayed removal should reset based on the most recent path disconnect time, but queue_delayed_work() won't do anything if the work is already pending. Attempt to cancel the delayed work when a new path connects, and use mod_delayed_work() in case the remove_work remains pending anyway. Signed-off-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Nilay Shroff <nilay@linux.ibm.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/nvme/host/core.c4
-rw-r--r--drivers/nvme/host/multipath.c2
2 files changed, 5 insertions, 1 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 92697f98c601..724f5732786c 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4036,6 +4036,10 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
list_add_tail_rcu(&ns->siblings, &head->list);
ns->head = head;
mutex_unlock(&ctrl->subsys->lock);
+
+#ifdef CONFIG_NVME_MULTIPATH
+ cancel_delayed_work(&head->remove_work);
+#endif
return 0;
out_put_ns_head:
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 140079ff86e6..1062467595f3 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -1311,7 +1311,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
*/
if (!try_module_get(THIS_MODULE))
goto out;
- queue_delayed_work(nvme_wq, &head->remove_work,
+ mod_delayed_work(nvme_wq, &head->remove_work,
head->delayed_removal_secs * HZ);
} else {
list_del_init(&head->entry);