<div dir="ltr">Applied.<div>Thanks.</div><div><br></div><div>Christophe Varoqui</div><div><a href="http://www.opensvc.com">www.opensvc.com</a></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Nov 14, 2013 at 1:09 AM, Sean Stewart <span dir="ltr"><<a href="mailto:sean.stewart@netapp.com" target="_blank">sean.stewart@netapp.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Make the RDAC checker utilize the RTPG data given in the 0xC9 inquiry<br>
page to make intelligent decisions about path status, and print more<br>
descriptive path down messages.<br>
<br>
Signed-off-by: Sean Stewart <<a href="mailto:sean.stewart@netapp.com">sean.stewart@netapp.com</a>><br>
---<br>
libmultipath/checkers/rdac.c | 92 ++++++++++++++++++++++++++++++++++++++------<br>
1 file changed, 81 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c<br>
index 2e64dd3..e0b2ea4 100644<br>
--- a/libmultipath/checkers/rdac.c<br>
+++ b/libmultipath/checkers/rdac.c<br>
@@ -34,6 +34,18 @@<br>
#define MSG_RDAC_UP "rdac checker reports path is up"<br>
#define MSG_RDAC_DOWN "rdac checker reports path is down"<br>
#define MSG_RDAC_GHOST "rdac checker reports path is ghost"<br>
+#define MSG_RDAC_DOWN_TYPE(STR) MSG_RDAC_DOWN": "STR<br>
+<br>
+#define RTPG_UNAVAILABLE 0x3<br>
+#define RTPG_OFFLINE 0xE<br>
+#define RTPG_TRANSITIONING 0xF<br>
+<br>
+#define RTPG_UNAVAIL_NON_RESPONSIVE 0x2<br>
+#define RTPG_UNAVAIL_IN_RESET 0x3<br>
+#define RTPG_UNAVAIL_CFW_DL1 0x4<br>
+#define RTPG_UNAVAIL_CFW_DL2 0x5<br>
+#define RTPG_UNAVAIL_QUIESCED 0x6<br>
+#define RTPG_UNAVAIL_SERVICE_MODE 0x7<br>
<br>
struct control_mode_page {<br>
unsigned char header[8];<br>
@@ -199,22 +211,64 @@ struct volume_access_inq<br>
char PQ_PDT;<br>
char dontcare0[7];<br>
char avtcvp;<br>
- char dontcare1;<br>
- char asym_access_state_cur;<br>
+ char vol_ppp;<br>
+ char aas_cur;<br>
char vendor_specific_cur;<br>
- char dontcare2[36];<br>
+ char aas_alt;<br>
+ char vendor_specific_alt;<br>
+ char dontcare1[34];<br>
};<br>
<br>
+const char<br>
+*checker_msg_string(struct volume_access_inq *inq)<br>
+{<br>
+ /* lun not connected */<br>
+ if (((inq->PQ_PDT & 0xE0) == 0x20) || (inq->PQ_PDT & 0x7f))<br>
+ return MSG_RDAC_DOWN_TYPE("lun not connected");<br>
+<br>
+ /* if no tpg data is available, give the generic path down message */<br>
+ if (!(inq->avtcvp & 0x10))<br>
+ return MSG_RDAC_DOWN;<br>
+<br>
+ /* controller is booting up */<br>
+ if (((inq->aas_cur & 0x0F) == RTPG_TRANSITIONING) &&<br>
+ (inq->aas_alt & 0x0F) != RTPG_TRANSITIONING)<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr is in startup sequence");<br>
+<br>
+ /* if not unavailable, give generic message */<br>
+ if ((inq->aas_cur & 0x0F) != RTPG_UNAVAILABLE)<br>
+ return MSG_RDAC_DOWN;<br>
+<br>
+ /* target port group unavailable */<br>
+ switch (inq->vendor_specific_cur) {<br>
+ case RTPG_UNAVAIL_NON_RESPONSIVE:<br>
+ return MSG_RDAC_DOWN_TYPE("non-responsive to queries");<br>
+ case RTPG_UNAVAIL_IN_RESET:<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr held in reset");<br>
+ case RTPG_UNAVAIL_CFW_DL1:<br>
+ case RTPG_UNAVAIL_CFW_DL2:<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr firmware downloading");<br>
+ case RTPG_UNAVAIL_QUIESCED:<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr quiesced by admin request");<br>
+ case RTPG_UNAVAIL_SERVICE_MODE:<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr is in service mode");<br>
+ default:<br>
+ return MSG_RDAC_DOWN_TYPE("ctlr is unavailable");<br>
+ }<br>
+}<br>
+<br>
extern int<br>
libcheck_check (struct checker * c)<br>
{<br>
struct volume_access_inq inq;<br>
- int ret;<br>
+ int ret, inqfail;<br>
<br>
+ inqfail = 0;<br>
memset(&inq, 0, sizeof(struct volume_access_inq));<br>
if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq),<br>
c->timeout)) {<br>
ret = PATH_DOWN;<br>
+ inqfail = 1;<br>
goto done;<br>
} else if (((inq.PQ_PDT & 0xE0) == 0x20) || (inq.PQ_PDT & 0x7f)) {<br>
/* LUN not connected*/<br>
@@ -222,12 +276,27 @@ libcheck_check (struct checker * c)<br>
goto done;<br>
}<br>
<br>
- /* check if controller is in service mode */<br>
- if ((inq.avtcvp & 0x10) &&<br>
- ((inq.asym_access_state_cur & 0x0F) == 0x3) &&<br>
- (inq.vendor_specific_cur == 0x7)) {<br>
- ret = PATH_DOWN;<br>
- goto done;<br>
+ /* If TPGDE bit set, evaluate TPG information */<br>
+ if ((inq.avtcvp & 0x10)) {<br>
+ switch (inq.aas_cur & 0x0F) {<br>
+ /* Never use the path if it reports unavailable */<br>
+ case RTPG_UNAVAILABLE:<br>
+ ret = PATH_DOWN;<br>
+ goto done;<br>
+ /*<br>
+ * If both controllers report transitioning, it<br>
+ * means mode select or STPG is being processed.<br>
+ *<br>
+ * If this controller alone is transitioning, it's<br>
+ * booting and we shouldn't use it yet.<br>
+ */<br>
+ case RTPG_TRANSITIONING:<br>
+ if ((inq.aas_alt & 0xF) != RTPG_TRANSITIONING) {<br>
+ ret = PATH_DOWN;<br>
+ goto done;<br>
+ }<br>
+ break;<br>
+ }<br>
}<br>
<br>
/* If owner set or ioship mode is enabled return PATH_UP always */<br>
@@ -239,7 +308,8 @@ libcheck_check (struct checker * c)<br>
done:<br>
switch (ret) {<br>
case PATH_DOWN:<br>
- MSG(c, MSG_RDAC_DOWN);<br>
+ MSG(c, (inqfail) ? MSG_RDAC_DOWN_TYPE("inquiry failed") :<br>
+ checker_msg_string(&inq));<br>
break;<br>
case PATH_UP:<br>
MSG(c, MSG_RDAC_UP);<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
</font></span></blockquote></div><br></div>