Make multipathd deal better with uninitialized paths
authorBenjamin Marzinski <bmarzins@redhat.com>
Thu, 2 May 2013 21:46:34 +0000 (16:46 -0500)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Mon, 6 May 2013 19:42:12 +0000 (21:42 +0200)
If multipathd cannot get all the necessary information from a path in
pathinfo, it clears the path's wwid, and adds it to the pathvec without
being initialized.  However, it never tries to reinitialize it later.
This can cause problems at bootup if multipathd is started at around
the same time as some path devices are discovered. multipathd may try
to initalize them in configure() before they are all the way set up.
After the paths are completely set up, multipathd will get a uevent for
them, but it won't try to reinitialize them. This patch adds
reinitialization code to uev_add_path().  Also, since getting the path
uid now just involves reading an attribute set by udev, there's no
reason no to try it for paths that are currently down.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
libmultipath/discovery.c
multipathd/main.c

index 4d452a1..26983ca 100644 (file)
@@ -1034,7 +1034,7 @@ pathinfo (struct path *pp, vector hwtable, int mask)
                }
        }
 
                }
        }
 
-       if (path_state == PATH_UP && (mask & DI_WWID) && !strlen(pp->wwid))
+       if ((mask & DI_WWID) && !strlen(pp->wwid))
                get_uid(pp);
        if (mask & DI_BLACKLIST && mask & DI_WWID) {
                if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
                get_uid(pp);
        if (mask & DI_BLACKLIST && mask & DI_WWID) {
                if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
index e5db3e8..8564819 100644 (file)
@@ -375,7 +375,7 @@ static int
 uev_add_path (struct uevent *uev, struct vectors * vecs)
 {
        struct path *pp;
 uev_add_path (struct uevent *uev, struct vectors * vecs)
 {
        struct path *pp;
-       int ret;
+       int ret, i;
 
        condlog(2, "%s: add path (uevent)", uev->kernel);
        if (strstr(uev->kernel, "..") != NULL) {
 
        condlog(2, "%s: add path (uevent)", uev->kernel);
        if (strstr(uev->kernel, "..") != NULL) {
@@ -392,6 +392,23 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
                        uev->kernel);
                if (pp->mpp)
                        return 0;
                        uev->kernel);
                if (pp->mpp)
                        return 0;
+               if (!strlen(pp->wwid)) {
+                       udev_device_unref(pp->udev);
+                       pp->udev = udev_device_ref(uev->udev);
+                       ret = pathinfo(pp, conf->hwtable,
+                                      DI_ALL | DI_BLACKLIST);
+                       if (ret == 2) {
+                               i = find_slot(vecs->pathvec, (void *)pp);
+                               if (i != -1)
+                                       vector_del_slot(vecs->pathvec, i);
+                               free_path(pp);
+                               return 0;
+                       } else if (ret == 1) {
+                               condlog(0, "%s: failed to reinitialize path",
+                                       uev->kernel);
+                               return 1;
+                       }
+               }
        } else {
                /*
                 * get path vital state
        } else {
                /*
                 * get path vital state