summaryrefslogtreecommitdiffstats
path: root/0069-UPBZ-1033791-improve-rdac-checker.patch
blob: c838f29ff95c7b0c5de54d45ff4f521ae88f7ab8 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
---
 libmultipath/checkers/rdac.c |   91 ++++++++++++++++++++++++++++++++++++++-----
 libmultipath/discovery.c     |    2 
 2 files changed, 81 insertions(+), 12 deletions(-)

Index: multipath-tools-130222/libmultipath/checkers/rdac.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/checkers/rdac.c
+++ multipath-tools-130222/libmultipath/checkers/rdac.c
@@ -34,6 +34,18 @@
 #define MSG_RDAC_UP    "rdac checker reports path is up"
 #define MSG_RDAC_DOWN  "rdac checker reports path is down"
 #define MSG_RDAC_GHOST "rdac checker reports path is ghost"
+#define MSG_RDAC_DOWN_TYPE(STR) MSG_RDAC_DOWN": "STR
+
+#define RTPG_UNAVAILABLE	0x3
+#define RTPG_OFFLINE		0xE
+#define RTPG_TRANSITIONING	0xF
+
+#define RTPG_UNAVAIL_NON_RESPONSIVE	0x2
+#define RTPG_UNAVAIL_IN_RESET		0x3
+#define RTPG_UNAVAIL_CFW_DL1		0x4
+#define RTPG_UNAVAIL_CFW_DL2		0x5
+#define RTPG_UNAVAIL_QUIESCED		0x6
+#define RTPG_UNAVAIL_SERVICE_MODE	0x7
 
 struct control_mode_page {
 	unsigned char header[8];
@@ -199,22 +211,64 @@ struct volume_access_inq
 	char PQ_PDT;
 	char dontcare0[7];
 	char avtcvp;
-	char dontcare1;
-	char asym_access_state_cur;
+	char vol_ppp;
+	char aas_cur;
 	char vendor_specific_cur;
-	char dontcare2[36];
+	char aas_alt;
+	char vendor_specific_alt;
+	char dontcare1[34];
 };
 
+const char
+*checker_msg_string(struct volume_access_inq *inq)
+{
+	/* lun not connected */
+	if (((inq->PQ_PDT & 0xE0) == 0x20) || (inq->PQ_PDT & 0x7f))
+		return MSG_RDAC_DOWN_TYPE("lun not connected");
+
+	/* if no tpg data is available, give the generic path down message */
+	if (!(inq->avtcvp & 0x10))
+		return MSG_RDAC_DOWN;
+
+	/* controller is booting up */
+	if (((inq->aas_cur & 0x0F) == RTPG_TRANSITIONING) &&
+		(inq->aas_alt & 0x0F) != RTPG_TRANSITIONING)
+		return MSG_RDAC_DOWN_TYPE("ctlr is in startup sequence");
+
+	/* if not unavailable, give generic message */
+	if ((inq->aas_cur & 0x0F) != RTPG_UNAVAILABLE)
+		return MSG_RDAC_DOWN;
+
+	/* target port group unavailable */
+	switch (inq->vendor_specific_cur) {
+	case RTPG_UNAVAIL_NON_RESPONSIVE:
+		return MSG_RDAC_DOWN_TYPE("non-responsive to queries");
+	case RTPG_UNAVAIL_IN_RESET:
+		return MSG_RDAC_DOWN_TYPE("ctlr held in reset");
+	case RTPG_UNAVAIL_CFW_DL1:
+	case RTPG_UNAVAIL_CFW_DL2:
+		return MSG_RDAC_DOWN_TYPE("ctlr firmware downloading");
+	case RTPG_UNAVAIL_QUIESCED:
+		return MSG_RDAC_DOWN_TYPE("ctlr quiesced by admin request");
+	case RTPG_UNAVAIL_SERVICE_MODE:
+		return MSG_RDAC_DOWN_TYPE("ctlr is in service mode");
+	default:
+		return MSG_RDAC_DOWN_TYPE("ctlr is unavailable");
+	}
+}
+
 extern int
 libcheck_check (struct checker * c)
 {
 	struct volume_access_inq inq;
-	int ret;
+	int ret, inqfail;
 
+	inqfail = 0;
 	memset(&inq, 0, sizeof(struct volume_access_inq));
 	if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq),
 			c->timeout)) {
 		ret = PATH_DOWN;
+		inqfail = 1;
 		goto done;
 	} else if (((inq.PQ_PDT & 0xE0) == 0x20) || (inq.PQ_PDT & 0x7f)) {
 		/* LUN not connected*/
@@ -222,11 +276,27 @@ libcheck_check (struct checker * c)
 		goto done;
 	}
 
-	/* check if controller is reporting asymmetric access state of unavailable */
-	if ((inq.avtcvp & 0x10) &&
-	    ((inq.asym_access_state_cur & 0x0F) == 0x3)) {
-		ret = PATH_DOWN;
-		goto done;
+	/* If TPGDE bit set, evaluate TPG information */
+	if ((inq.avtcvp & 0x10)) {
+		switch (inq.aas_cur & 0x0F) {
+		/* Never use the path if it reports unavailable */
+		case RTPG_UNAVAILABLE:
+			ret = PATH_DOWN;
+			goto done;
+		/*
+		 * If both controllers report transitioning, it
+		 * means mode select or STPG is being processed.
+		 *
+		 * If this controller alone is transitioning, it's
+		 * booting and we shouldn't use it yet.
+		 */
+		case RTPG_TRANSITIONING:
+			if ((inq.aas_alt & 0xF) != RTPG_TRANSITIONING) {
+				ret = PATH_DOWN;
+				goto done;
+			}
+			break;
+		}
 	}
 
 	/* If owner set or ioship mode is enabled return PATH_UP always */
@@ -238,7 +308,8 @@ libcheck_check (struct checker * c)
 done:
 	switch (ret) {
 	case PATH_DOWN:
-		MSG(c, MSG_RDAC_DOWN);
+		MSG(c, (inqfail) ? MSG_RDAC_DOWN_TYPE("inquiry failed") :
+			checker_msg_string(&inq));
 		break;
 	case PATH_UP:
 		MSG(c, MSG_RDAC_UP);
Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -1116,8 +1116,6 @@ pathinfo (struct path *pp, vector hwtabl
 			if (!strlen(pp->wwid))
 				get_uid(pp);
 			get_prio(pp);
-		} else {
-			pp->priority = PRIO_UNDEF;
 		}
 	}