libmultipath: fix ALUA autodetection when paths are down
authorMartin Wilck <mwilck@suse.com>
Fri, 15 Nov 2019 14:41:54 +0000 (14:41 +0000)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Mon, 2 Mar 2020 23:32:31 +0000 (00:32 +0100)
If a single path was offline when detect_alua() was called,
multipathd would assume ALUA was generally unsupported.

Fix that by assuming that if at least one path has ALUA support and
no path explicitly does not have it, ALUA is supported.

Signed-off-by: Martin Wilck <mwilck@suse.com>
libmultipath/discovery.c
libmultipath/propsel.c

index 99c1a0f..ee3290c 100644 (file)
@@ -876,6 +876,10 @@ get_serial (char * str, int maxlen, int fd)
        return 1;
 }
 
+/*
+ * Side effect: sets pp->tpgs if it could be determined.
+ * If ALUA calls fail because paths are unreachable, pp->tpgs remains unchanged.
+ */
 static void
 detect_alua(struct path * pp)
 {
@@ -886,12 +890,28 @@ detect_alua(struct path * pp)
        if (sysfs_get_timeout(pp, &timeout) <= 0)
                timeout = DEF_TIMEOUT;
 
-       if ((tpgs = get_target_port_group_support(pp, timeout)) <= 0) {
+       tpgs = get_target_port_group_support(pp, timeout);
+       if (tpgs == -RTPG_INQUIRY_FAILED)
+               return;
+       else if (tpgs <= 0) {
                pp->tpgs = TPGS_NONE;
                return;
        }
+
+       if (pp->fd == -1 || pp->offline)
+               return;
+
        ret = get_target_port_group(pp, timeout);
        if (ret < 0 || get_asymmetric_access_state(pp, ret, timeout) < 0) {
+               int state;
+
+               if (ret == -RTPG_INQUIRY_FAILED)
+                       return;
+
+               state = path_offline(pp);
+               if (state == PATH_DOWN || state == PATH_PENDING)
+                       return;
+
                pp->tpgs = TPGS_NONE;
                return;
        }
index 2808102..897e48c 100644 (file)
@@ -432,12 +432,26 @@ int select_hwhandler(struct config *conf, struct multipath *mp)
        static const char tpgs_origin[]= "(setting: autodetected from TPGS)";
        char *dh_state;
        int i;
-       bool all_tpgs = true;
+       bool all_tpgs = true, one_tpgs = false;
 
        dh_state = &handler[2];
 
-       vector_foreach_slot(mp->paths, pp, i)
-               all_tpgs = all_tpgs && (path_get_tpgs(pp) > 0);
+       /*
+        * TPGS_UNDEF means that ALUA support couldn't determined either way
+        * yet, probably because the path was always down.
+        * If at least one path does have TPGS support, and no path has
+        * TPGS_NONE, assume that TPGS would be supported by all paths if
+        * all were up.
+        */
+       vector_foreach_slot(mp->paths, pp, i) {
+               int tpgs = path_get_tpgs(pp);
+
+               all_tpgs = all_tpgs && tpgs != TPGS_NONE;
+               one_tpgs = one_tpgs ||
+                       (tpgs != TPGS_NONE && tpgs != TPGS_UNDEF);
+       }
+       all_tpgs = all_tpgs && one_tpgs;
+
        if (mp->retain_hwhandler != RETAIN_HWHANDLER_OFF) {
                vector_foreach_slot(mp->paths, pp, i) {
                        if (get_dh_state(pp, dh_state, sizeof(handler) - 2) > 0