libmulitpath: cleanup uid_fallback code
[multipath-tools/.git] / libmultipath / discovery.c
index 3550c3a..3ec60d6 100644 (file)
@@ -103,6 +103,7 @@ store_pathinfo (vector pathvec, struct config *conf,
        err = store_path(pathvec, pp);
        if (err)
                goto out;
+       pp->checkint = conf->checkint;
 
 out:
        if (err)
@@ -519,7 +520,7 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
                /* Parse error, ignore */
                return 0;
        }
-       return  preferred;
+       return !!preferred;
 }
 
 static void
@@ -710,7 +711,7 @@ sysfs_set_scsi_tmo (struct multipath *mpp, int checkint)
        int dev_loss_tmo = mpp->dev_loss;
 
        if (mpp->no_path_retry > 0) {
-               uint64_t no_path_retry_tmo = mpp->no_path_retry * checkint;
+               uint64_t no_path_retry_tmo = (uint64_t)mpp->no_path_retry * checkint;
 
                if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
                        no_path_retry_tmo = MAX_DEV_LOSS_TMO;
@@ -1105,7 +1106,9 @@ get_vpd_sgio (int fd, int pg, char * str, int maxlen)
 
        memset(buff, 0x0, 4096);
        if (sgio_get_vpd(buff, 4096, fd, pg) < 0) {
-               condlog(3, "failed to issue vpd inquiry for pg%02x",
+               int lvl = pg == 0x80 || pg == 0x83 ? 3 : 4;
+
+               condlog(lvl, "failed to issue vpd inquiry for pg%02x",
                        pg);
                return -errno;
        }
@@ -1381,7 +1384,7 @@ common_sysfs_pathinfo (struct path * pp)
        devt = udev_device_get_devnum(pp->udev);
        snprintf(pp->dev_t, BLK_DEV_SIZE, "%d:%d", major(devt), minor(devt));
 
-       condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
+       condlog(4, "%s: dev_t = %s", pp->dev, pp->dev_t);
 
        if (sysfs_get_size(pp, &pp->size))
                return PATHINFO_FAILED;
@@ -1432,7 +1435,7 @@ path_offline (struct path * pp)
        }
 
 
-       condlog(3, "%s: path state = %s", pp->dev, buff);
+       condlog(4, "%s: path state = %s", pp->dev, buff);
 
        if (pp->bus == SYSFS_BUS_SCSI) {
                if (!strncmp(buff, "offline", 7)) {
@@ -1551,8 +1554,6 @@ get_state (struct path * pp, struct config *conf, int daemon, int oldstate)
        struct checker * c = &pp->checker;
        int state;
 
-       condlog(3, "%s: get_state", pp->dev);
-
        if (!checker_selected(c)) {
                if (daemon) {
                        if (pathinfo(pp, conf, DI_SYSFS) != PATHINFO_OK) {
@@ -1589,8 +1590,8 @@ get_state (struct path * pp, struct config *conf, int daemon, int oldstate)
                checker_name(c), checker_state_name(state));
        if (state != PATH_UP && state != PATH_GHOST &&
            strlen(checker_message(c)))
-               condlog(3, "%s: checker msg is \"%s\"",
-                       pp->dev, checker_message(c));
+               condlog(3, "%s: %s checker%s",
+                       pp->dev, checker_name(c), checker_message(c));
        return state;
 }
 
@@ -1600,6 +1601,7 @@ get_prio (struct path * pp)
        struct prio * p;
        struct config *conf;
        int checker_timeout;
+       int old_prio;
 
        if (!pp)
                return 0;
@@ -1620,13 +1622,14 @@ get_prio (struct path * pp)
        conf = get_multipath_config();
        checker_timeout = conf->checker_timeout;
        put_multipath_config(conf);
+       old_prio = pp->priority;
        pp->priority = prio_getprio(p, pp, checker_timeout);
        if (pp->priority < 0) {
                condlog(3, "%s: %s prio error", pp->dev, prio_name(p));
                pp->priority = PRIO_UNDEF;
                return 1;
        }
-       condlog(3, "%s: %s prio = %u",
+       condlog((old_prio == pp->priority ? 4 : 3), "%s: %s prio = %u",
                pp->dev, prio_name(p), pp->priority);
        return 0;
 }
@@ -1751,17 +1754,12 @@ get_vpd_uid(struct path * pp)
        return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
 }
 
-static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
-                            const char **origin)
+static ssize_t uid_fallback(struct path *pp, int path_state,
+                           const char **origin)
 {
-       ssize_t len = 0;
-       int retrigger;
-       struct config *conf;
+       ssize_t len = -1;
 
-       conf = get_multipath_config();
-       retrigger = conf->retrigger_tries;
-       put_multipath_config(conf);
-       if (pp->retriggers >= retrigger &&
+       if (pp->bus == SYSFS_BUS_SCSI &&
            !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
                len = get_vpd_uid(pp);
                *origin = "sysfs";
@@ -1773,10 +1771,34 @@ static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
                                           WWID_SIZE);
                        *origin = "sgio";
                }
+       } else if (pp->bus == SYSFS_BUS_NVME) {
+               char value[256];
+               len = sysfs_attr_get_value(pp->udev, "wwid", value,
+                                          sizeof(value));
+               if (len <= 0)
+                       return -1;
+               len = strlcpy(pp->wwid, value, WWID_SIZE);
+               if (len >= WWID_SIZE) {
+                       len = fix_broken_nvme_wwid(pp, value,
+                                                  WWID_SIZE);
+                       if (len > 0)
+                               return len;
+                       condlog(0, "%s: wwid overflow", pp->dev);
+                       len = WWID_SIZE;
+               }
+               *origin = "sysfs";
+               pp->uid_attribute = NULL;
        }
        return len;
 }
 
+static int has_uid_fallback(struct path *pp)
+{
+       return ((pp->bus == SYSFS_BUS_SCSI &&
+                !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) ||
+               pp->bus == SYSFS_BUS_NVME);
+}
+
 int
 get_uid (struct path * pp, int path_state, struct udev_device *udev)
 {
@@ -1824,8 +1846,15 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev)
                        len = get_vpd_uid(pp);
                        origin = "sysfs";
                }
-               if (len <= 0 && pp->bus == SYSFS_BUS_SCSI)
-                       len = scsi_uid_fallback(pp, path_state, &origin);
+               if (len <= 0 && has_uid_fallback(pp)) {
+                       int retrigger_tries;
+
+                       conf = get_multipath_config();
+                       retrigger_tries = conf->retrigger_tries;
+                       put_multipath_config(conf);
+                       if (pp->retriggers >= retrigger_tries)
+                               len = uid_fallback(pp, path_state, &origin);
+               }
        }
        if ( len < 0 ) {
                condlog(1, "%s: failed to get %s uid: %s",
@@ -1864,11 +1893,11 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
                        udev_device_get_sysattr_value(pp->udev, "hidden");
 
                if (hidden && !strcmp(hidden, "1")) {
-                       condlog(3, "%s: hidden", pp->dev);
+                       condlog(4, "%s: hidden", pp->dev);
                        return PATHINFO_SKIPPED;
                }
                if (is_claimed_by_foreign(pp->udev) ||
-                        filter_property(conf, pp->udev) > 0)
+                   filter_property(conf, pp->udev, 4) > 0)
                        return PATHINFO_SKIPPED;
        }
 
@@ -1877,7 +1906,7 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
                           pp->dev) > 0)
                return PATHINFO_SKIPPED;
 
-       condlog(3, "%s: mask = 0x%x", pp->dev, mask);
+       condlog(4, "%s: mask = 0x%x", pp->dev, mask);
 
        /*
         * Sanity check: we need the device number to
@@ -1911,11 +1940,12 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
        if (path_state == PATH_REMOVED)
                goto blank;
        else if (mask & DI_NOIO) {
-               /*
-                * Avoid any IO on the device itself.
-                * Behave like DI_CHECKER in the "path unavailable" case.
-                */
-               pp->chkrstate = pp->state = path_state;
+               if (mask & DI_CHECKER)
+                       /*
+                        * Avoid any IO on the device itself.
+                        * simply use the path_offline() return as its state
+                        */
+                       pp->chkrstate = pp->state = path_state;
                return PATHINFO_OK;
        }
 
@@ -1942,11 +1972,11 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
 
        if (mask & DI_CHECKER) {
                if (path_state == PATH_UP) {
-                       pp->chkrstate = pp->state = get_state(pp, conf, 0,
-                                                             path_state);
-                       if (pp->state == PATH_UNCHECKED ||
+                       int newstate = get_state(pp, conf, 0, path_state);
+                       if (newstate != PATH_PENDING ||
+                           pp->state == PATH_UNCHECKED ||
                            pp->state == PATH_WILD)
-                               goto blank;
+                               pp->chkrstate = pp->state = newstate;
                        if (pp->state == PATH_TIMEOUT)
                                pp->state = PATH_DOWN;
                        if (pp->state == PATH_UP && !pp->size) {
@@ -1966,8 +1996,12 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
        if ((mask & DI_WWID) && !strlen(pp->wwid)) {
                get_uid(pp, path_state, pp->udev);
                if (!strlen(pp->wwid)) {
-                       pp->initialized = INIT_MISSING_UDEV;
-                       pp->tick = conf->retrigger_delay;
+                       if (pp->bus == SYSFS_BUS_UNDEF)
+                               return PATHINFO_SKIPPED;
+                       if (pp->initialized != INIT_FAILED) {
+                               pp->initialized = INIT_MISSING_UDEV;
+                               pp->tick = conf->retrigger_delay;
+                       }
                        return PATHINFO_OK;
                }
                else
@@ -2000,7 +2034,7 @@ blank:
         * Recoverable error, for example faulty or offline path
         */
        pp->chkrstate = pp->state = PATH_DOWN;
-       if (pp->initialized == INIT_FAILED)
+       if (pp->initialized == INIT_NEW || pp->initialized == INIT_FAILED)
                memset(pp->wwid, 0, WWID_SIZE);
 
        return PATHINFO_OK;