<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>