56 lines
2.2 KiB
Diff
56 lines
2.2 KiB
Diff
|
|
From 4098378d2e976c9b371ae6bf83e802fb32187f50 Mon Sep 17 00:00:00 2001
|
||
|
|
From: sunguoshuai <sunguoshuai@huawei.com>
|
||
|
|
Date: Tue, 22 Jan 2019 21:29:56 -0500
|
||
|
|
Subject: [PATCH] multipathd: disable queueing for recreated map in
|
||
|
|
uev_remove_map
|
||
|
|
|
||
|
|
reason:disable queueing for recreated map in uev_remove_map
|
||
|
|
---
|
||
|
|
multipathd/main.c | 23 +++++++++++++++++++++--
|
||
|
|
1 file changed, 21 insertions(+), 2 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||
|
|
index cc493c1..9dd74ad 100644
|
||
|
|
--- a/multipathd/main.c
|
||
|
|
+++ b/multipathd/main.c
|
||
|
|
@@ -647,7 +647,7 @@ uev_add_map (struct uevent * uev, struct vectors * vecs)
|
||
|
|
char *alias;
|
||
|
|
int major = -1, minor = -1, rc;
|
||
|
|
|
||
|
|
- condlog(3, "%s: add map (uevent)", uev->kernel);
|
||
|
|
+ condlog(2, "%s: add map (uevent)", uev->kernel);
|
||
|
|
alias = uevent_get_dm_name(uev);
|
||
|
|
if (!alias) {
|
||
|
|
condlog(3, "%s: No DM_NAME in uevent", uev->kernel);
|
||
|
|
@@ -766,7 +766,26 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs)
|
||
|
|
mpp->alias, mpp->dmi->minor, minor);
|
||
|
|
goto out;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
+ /*
|
||
|
|
+ * There may be a race window here:
|
||
|
|
+ * 1. all paths gone, causing map flushed both from multipathd and kernel
|
||
|
|
+ * 2. paths regenerated, causing multipathd creating the map again.
|
||
|
|
+ * 1 will generate a remove uevent which can be handled after 2,
|
||
|
|
+ * so we can disable queueing for the map created by 2 here temporarily
|
||
|
|
+ * and let the change uevent (generated by 2) calling uev_add_map
|
||
|
|
+ * ->setup_multipath to set queueing again. This can prevent
|
||
|
|
+ * the deadlock in this race window.
|
||
|
|
+ *
|
||
|
|
+ * The possible deadlock is: all udevd workers hangs in
|
||
|
|
+ * devices because of queue_if_no_path, so no udevd workers
|
||
|
|
+ * can handle new event and since multipathd will remove the map,
|
||
|
|
+ * the checkerloop cannot check this map's retry tick timeout
|
||
|
|
+ * and cancel the io hang which makes the udevd worker hang forever.
|
||
|
|
+ * multipathd cannot receive any uevent from udevd because all
|
||
|
|
+ * udevd workers hang there so the map cannot be recreated
|
||
|
|
+ * again which makes a deadlock.
|
||
|
|
+ */
|
||
|
|
+ dm_queue_if_no_path(alias, 0);
|
||
|
|
orphan_paths(vecs->pathvec, mpp);
|
||
|
|
remove_map_and_stop_waiter(mpp, vecs);
|
||
|
|
out:
|
||
|
|
--
|
||
|
|
1.8.3.1
|
||
|
|
|