summaryrefslogtreecommitdiffstats
path: root/0010-call-start_waiter_thread-before-setup_multipath.patch
blob: bb5a479d85a975c4fe807d0fe348d3475c93cb18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 21:59:16 -0600
Subject: [PATCH] call start_waiter_thread() before setup_multipath()

If setup_multipath() is called before the waiter thread has started,
there is a window where a dm event can occur between when
setup_multipath() updates the device state and when the waiter thread
starts waiting for new events, causing the new event to be missed and
the multipath device to not get updated.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
 multipathd/main.c | 37 ++++++++++++++++++++-----------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/multipathd/main.c b/multipathd/main.c
index 94b2406..efc39d7 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -321,7 +321,7 @@ set_multipath_wwid (struct multipath * mpp)
 }
 
 static int
-update_map (struct multipath *mpp, struct vectors *vecs)
+update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
 {
 	int retries = 3;
 	char params[PARAMS_SIZE] = {0};
@@ -351,6 +351,12 @@ retry:
 	dm_lib_release();
 
 fail:
+	if (new_map && (retries < 0 || start_waiter_thread(mpp, vecs))) {
+		condlog(0, "%s: failed to create new map", mpp->alias);
+		remove_map(mpp, vecs, 1);
+		return 1;
+	}
+
 	if (setup_multipath(vecs, mpp))
 		return 1;
 
@@ -395,12 +401,9 @@ add_map_without_path (struct vectors *vecs, char *alias)
 
 	vector_set_slot(vecs->mpvec, mpp);
 
-	if (update_map(mpp, vecs) != 0) /* map removed */
+	if (update_map(mpp, vecs, 1) != 0) /* map removed */
 		return NULL;
 
-	if (start_waiter_thread(mpp, vecs))
-		goto out;
-
 	return mpp;
 out:
 	remove_map(mpp, vecs, PURGE_VEC);
@@ -554,7 +557,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
 		if (mpp->wait_for_udev > 1) {
 			condlog(2, "%s: performing delayed actions",
 				mpp->alias);
-			if (update_map(mpp, vecs))
+			if (update_map(mpp, vecs, 0))
 				/* setup multipathd removed the map */
 				return 1;
 		}
@@ -865,6 +868,11 @@ retry:
 	}
 	dm_lib_release();
 
+	if ((mpp->action == ACT_CREATE ||
+	     (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
+	    start_waiter_thread(mpp, vecs))
+			goto fail_map;
+
 	/*
 	 * update our state from kernel regardless of create or reload
 	 */
@@ -873,11 +881,6 @@ retry:
 
 	sync_map_state(mpp);
 
-	if ((mpp->action == ACT_CREATE ||
-	     (mpp->action == ACT_NOTHING && start_waiter && !mpp->waiter)) &&
-	    start_waiter_thread(mpp, vecs))
-			goto fail_map;
-
 	if (retries >= 0) {
 		condlog(2, "%s [%s]: path added to devmap %s",
 			pp->dev, pp->dev_t, mpp->alias);
@@ -1479,7 +1482,8 @@ missing_uev_wait_tick(struct vectors *vecs)
 		if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) {
 			timed_out = 1;
 			condlog(0, "%s: timeout waiting on creation uevent. enabling reloads", mpp->alias);
-			if (mpp->wait_for_udev > 1 && update_map(mpp, vecs)) {
+			if (mpp->wait_for_udev > 1 &&
+			    update_map(mpp, vecs, 0)) {
 				/* update_map removed map */
 				i--;
 				continue;
@@ -1511,7 +1515,7 @@ ghost_delay_tick(struct vectors *vecs)
 			condlog(0, "%s: timed out waiting for active path",
 				mpp->alias);
 			mpp->force_udev_reload = 1;
-			if (update_map(mpp, vecs) != 0) {
+			if (update_map(mpp, vecs, 0) != 0) {
 				/* update_map removed map */
 				i--;
 				continue;
@@ -2169,14 +2173,13 @@ configure (struct vectors * vecs)
 	 * start dm event waiter threads for these new maps
 	 */
 	vector_foreach_slot(vecs->mpvec, mpp, i) {
-		if (setup_multipath(vecs, mpp)) {
-			i--;
-			continue;
-		}
 		if (start_waiter_thread(mpp, vecs)) {
 			remove_map(mpp, vecs, 1);
 			i--;
+			continue;
 		}
+		if (setup_multipath(vecs, mpp))
+			i--;
 	}
 	return 0;
 }
-- 
2.7.4