libmultipath: lazy tpgs probing
authorMartin Wilck <mwilck@suse.com>
Mon, 18 Mar 2019 11:24:41 +0000 (12:24 +0100)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Thu, 18 Apr 2019 11:07:27 +0000 (13:07 +0200)
Provide a "getter" function that can be used to probe tpgs lazily.
This way we don't need to send an RTPG in the pathinfo() call
chain (e.g. in "multipath -u"). With this in place, no "user"
code should access pp->tpgs directly any more.

Moreover, in select_prio(), in the case where the alua checker
was statically configured, rather then calling into the alua
code directly, use get_tpgs(), which does all the proper error
checking, and fall back to const prio if it fails.

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

index 64c827a..00ffd06 100644 (file)
@@ -854,6 +854,13 @@ detect_alua(struct path * pp)
        pp->tpgs = tpgs;
 }
 
+int path_get_tpgs(struct path *pp)
+{
+       if (pp->tpgs == TPGS_UNDEF)
+               detect_alua(pp);
+       return pp->tpgs;
+}
+
 #define DEFAULT_SGIO_LEN 254
 
 /* Query VPD page @pg. Returns number of INQUIRY bytes
@@ -1521,9 +1528,6 @@ scsi_ioctl_pathinfo (struct path * pp, struct config *conf, int mask)
        struct udev_device *parent;
        const char *attr_path = NULL;
 
-       if (pp->tpgs == TPGS_UNDEF)
-               detect_alua(pp);
-
        if (!(mask & DI_SERIAL))
                return;
 
index 4e3b984..8d04c2a 100644 (file)
@@ -31,7 +31,7 @@
 struct config;
 
 int path_discovery (vector pathvec, int flag);
-
+int path_get_tpgs(struct path *pp); /* This function never returns TPGS_UNDEF */
 int do_tur (char *);
 int path_offline (struct path *);
 int get_state (struct path * pp, struct config * conf, int daemon, int state);
index 624dc6e..27474f0 100644 (file)
@@ -425,7 +425,7 @@ int select_hwhandler(struct config *conf, struct multipath *mp)
        dh_state = &handler[2];
 
        vector_foreach_slot(mp->paths, pp, i)
-               all_tpgs = all_tpgs && (pp->tpgs > 0);
+               all_tpgs = all_tpgs && (path_get_tpgs(pp) > 0);
        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
@@ -490,7 +490,7 @@ int select_checker(struct config *conf, struct path *pp)
                if (check_rdac(pp)) {
                        ckr_name = RDAC;
                        goto out;
-               } else if (pp->tpgs > 0) {
+               } else if (path_get_tpgs(pp) != TPGS_NONE) {
                        ckr_name = TUR;
                        goto out;
                }
@@ -552,6 +552,7 @@ detect_prio(struct config *conf, struct path * pp)
        struct prio *p = &pp->prio;
        char buff[512];
        char *default_prio;
+       int tpgs;
 
        switch(pp->bus) {
        case SYSFS_BUS_NVME:
@@ -560,9 +561,10 @@ detect_prio(struct config *conf, struct path * pp)
                default_prio = PRIO_ANA;
                break;
        case SYSFS_BUS_SCSI:
-               if (pp->tpgs <= 0)
+               tpgs = path_get_tpgs(pp);
+               if (tpgs == TPGS_NONE)
                        return;
-               if ((pp->tpgs == 2 || !check_rdac(pp)) &&
+               if ((tpgs == TPGS_EXPLICIT || !check_rdac(pp)) &&
                    sysfs_get_asymmetric_access_state(pp, buff, 512) >= 0)
                        default_prio = PRIO_SYSFS;
                else
@@ -607,6 +609,7 @@ int select_prio(struct config *conf, struct path *pp)
        const char *origin;
        struct mpentry * mpe;
        struct prio * p = &pp->prio;
+       int log_prio = 3;
 
        if (pp->detect_prio == DETECT_PRIO_ON) {
                detect_prio(conf, pp);
@@ -628,14 +631,16 @@ out:
         * fetch tpgs mode for alua, if its not already obtained
         */
        if (!strncmp(prio_name(p), PRIO_ALUA, PRIO_NAME_LEN)) {
-               int tpgs = 0;
-               unsigned int timeout = conf->checker_timeout;
+               int tpgs = path_get_tpgs(pp);
 
-               if(!pp->tpgs &&
-                  (tpgs = get_target_port_group_support(pp, timeout)) >= 0)
-                       pp->tpgs = tpgs;
+               if (tpgs == TPGS_NONE) {
+                       prio_get(conf->multipath_dir,
+                                p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
+                       origin = "(setting: emergency fallback - alua failed)";
+                       log_prio = 1;
+               }
        }
-       condlog(3, "%s: prio = %s %s", pp->dev, prio_name(p), origin);
+       condlog(log_prio, "%s: prio = %s %s", pp->dev, prio_name(p), origin);
        condlog(3, "%s: prio args = \"%s\" %s", pp->dev, prio_args(p), origin);
        return 0;
 }
index c8a8529..f203d77 100644 (file)
@@ -950,7 +950,8 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
        }
        if (mpp && mpp->wait_for_udev &&
            (pathcount(mpp, PATH_UP) > 0 ||
-            (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT &&
+            (pathcount(mpp, PATH_GHOST) > 0 &&
+             path_get_tpgs(pp) != TPGS_IMPLICIT &&
              mpp->ghost_delay_tick <= 0))) {
                /* if wait_for_udev is set and valid paths exist */
                condlog(3, "%s: delaying path addition until %s is fully initialized",
@@ -2108,8 +2109,8 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
         * paths if there are no other active paths in map.
         */
        disable_reinstate = (newstate == PATH_GHOST &&
-                           pp->mpp->nr_active == 0 &&
-                           pp->tpgs == TPGS_IMPLICIT) ? 1 : 0;
+                            pp->mpp->nr_active == 0 &&
+                            path_get_tpgs(pp) == TPGS_IMPLICIT) ? 1 : 0;
 
        pp->chkrstate = newstate;
        if (newstate != pp->state) {