multipath: handle offlined paths
authorBenjamin Marzinski <bmarzins@redhat.com>
Mon, 17 Oct 2011 21:16:02 +0000 (16:16 -0500)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Mon, 17 Oct 2011 22:06:06 +0000 (00:06 +0200)
The kernel does not allow multipath to load tables containing offline
devices. Because of this, if you try add a path to a multipath device with
an offline path, the multipathd will continually, retry and fail to reload
the table. I've limited the retries to three to avoid livelocking.

Also, if you map included a offline path, multipath was crashing because
it couldn't get the required sysfs information before calling get_state().
It now checks for this in multipath, like it does in multipathd

Lastly, multipathd would keep reprinting the last checker message for
offlined paths, instead of something useful. It now prints a "path offline"
message.

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

index dac97a3ffbabf474f3b94f68554e241f0f7783df..fdcffe782b8a855a5f775686f322bb15d1b371e1 100644 (file)
@@ -805,8 +805,13 @@ get_state (struct path * pp, int daemon)
        condlog(3, "%s: get_state", pp->dev);
 
        if (!checker_selected(c)) {
-               if (daemon)
-                       pathinfo(pp, conf->hwtable, DI_SYSFS);
+               if (daemon || pp->sysdev == NULL) {
+                       if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) {
+                               condlog(3, "%s: couldn't get sysfs pathinfo",
+                                       pp->dev);
+                               return PATH_UNCHECKED;
+                       }
+               }
                select_checker(pp);
                if (!checker_selected(c)) {
                        condlog(3, "%s: No checker selected", pp->dev);
index 5038d6757640a828c6e0bd2fdbb1453878ae4265..02df98dd2c4137d0e037a04d47332b1d26d2c4f8 100644 (file)
 #define FILE_NAME_SIZE 256
 #define CMDSIZE 160
 
-#define LOG_MSG(a,b) \
-       if (strlen(b)) condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b);
+#define LOG_MSG(a, b) \
+do { \
+       if (pp->offline) \
+               condlog(a, "%s: %s - path offline", pp->mpp->alias, pp->dev); \
+       else if (strlen(b)) \
+               condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b); \
+} while(0)
 
 pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
 pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -365,6 +370,7 @@ ev_add_path (char * devname, struct vectors * vecs)
        struct path * pp;
        char empty_buff[WWID_SIZE] = {0};
        char params[PARAMS_SIZE] = {0};
+       int retries = 3;
        int start_waiter = 0;
 
        if (strstr(devname, "..") != NULL) {
@@ -478,12 +484,14 @@ rescan:
                /*
                 * deal with asynchronous uevents :((
                 */
-               if (mpp->action == ACT_RELOAD) {
+               if (mpp->action == ACT_RELOAD && retries-- > 0) {
                        condlog(0, "%s: uev_add_path sleep", mpp->alias);
                        sleep(1);
                        update_mpp_paths(mpp, vecs->pathvec);
                        goto rescan;
                }
+               else if (mpp->action == ACT_RELOAD)
+                       condlog(0, "%s: giving up reload", mpp->alias);
                else
                        goto fail_map;
        }
@@ -502,8 +510,12 @@ rescan:
            start_waiter_thread(mpp, vecs))
                        goto fail_map;
 
-       condlog(2, "%s path added to devmap %s", devname, mpp->alias);
-       return 0;
+       if (retries >= 0) {
+               condlog(2, "%s path added to devmap %s", devname, mpp->alias);
+               return 0;
+       }
+       else
+               return 1;
 
 fail_map:
        remove_map(mpp, vecs, 1);