Commit dd2c1854 authored by Keith Busch's avatar Keith Busch Committed by Christoph Hellwig
Browse files

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: default avatarKeith Busch <kbusch@kernel.org>
Reviewed-by: default avatarNilay Shroff <nilay@linux.ibm.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 4c8a9517
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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:
+1 −1
Original line number Diff line number Diff line
@@ -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);