[multipathd] use DM rename instead of a remove/create cycle
authorChristophe Varoqui <root@xa-s05.(none)>
Tue, 22 Nov 2005 13:16:13 +0000 (14:16 +0100)
committerChristophe Varoqui <root@xa-s05.(none)>
Tue, 22 Nov 2005 13:16:13 +0000 (14:16 +0100)
This patch depends on a kernel patch yet to be merged. Beware.

Also fixed callers of dm_info() to check for <=0 as an error instead of
just == 0.

Edward Goggin, EMC.

libmultipath/configure.c
libmultipath/configure.h
libmultipath/devmapper.c
libmultipath/devmapper.h
libmultipath/structs.c
libmultipath/structs.h
libmultipath/structs_vec.c
libmultipath/structs_vec.h
multipathd/main.c

index 65255d3..9b3d680 100644 (file)
@@ -137,9 +137,15 @@ select_action (struct multipath * mpp, vector curmp)
                cmpp = find_mp_by_wwid(curmp, mpp->wwid);
 
                if (cmpp && !conf->dry_run) {
-                       condlog(2, "remove: %s (dup of %s)",
+                       condlog(2, "%s: rename: %s to %s", mpp->wwid,
                                cmpp->alias, mpp->alias);
                        dm_flush_map(cmpp->alias, DEFAULT_TARGET);
+                       strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+                       mpp->action = ACT_RENAME;
+               }
+               else {
+                       condlog(3, "set ACT_CREATE: map does not exist");
+                       mpp->action = ACT_CREATE;
                }
                mpp->action = ACT_CREATE;
                condlog(3, "set ACT_CREATE: map does not exists");
@@ -148,7 +154,7 @@ select_action (struct multipath * mpp, vector curmp)
 
        if (!find_mp_by_wwid(curmp, mpp->wwid)) {
                condlog(2, "remove: %s (wwid changed)", cmpp->alias);
-               dm_flush_map(mpp->alias, NULL);
+               dm_flush_map(mpp->alias, DEFAULT_TARGET);
                strncat(cmpp->wwid, mpp->wwid, WWID_SIZE);
                drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
                mpp->action = ACT_CREATE;
@@ -321,7 +327,7 @@ domap (struct multipath * mpp)
                        condlog(3, "%s: failed to load map "
                                   "(a path might be in use)",
                                   mpp->alias);
-                       dm_flush_map(mpp->alias, NULL);
+                       dm_flush_map(mpp->alias, DEFAULT_TARGET);
                }
 
                lock_multipath(mpp, 0);
@@ -334,13 +340,18 @@ domap (struct multipath * mpp)
                     dm_simplecmd(DM_DEVICE_RESUME, mpp->alias));
                break;
 
+       case ACT_RENAME:
+               r = dm_rename(mpp->alias_old, mpp->alias);
+               break;
+
        default:
                break;
        }
 
        if (r) {
                /*
-                * DM_DEVICE_CREATE or DM_DEVICE_RELOAD succeeded
+                * DM_DEVICE_CREATE, DM_DEIVCE_RENAME, or DM_DEVICE_RELOAD
+                * succeeded
                 */
 #ifndef DAEMON
                dm_switchgroup(mpp->alias, mpp->bestpg);
@@ -412,8 +423,11 @@ coalesce_paths (struct vectors * vecs, vector newmp)
                if (pp1->priority < 0)
                        mpp->action = ACT_REJECT;
 
-               if (!mpp->paths)
-                       return 1;
+               if (!mpp->paths) {
+                       condlog(0, "%s coalesce_paths: no paths", mpp->alias);
+                       remove_map(mpp, vecs, NULL, 0);
+                       continue;
+               }
                
                for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
                        pp2 = VECTOR_SLOT(pathvec, i);
@@ -449,13 +463,18 @@ coalesce_paths (struct vectors * vecs, vector newmp)
                r = domap(mpp);
 
                if (!r) {
-                       condlog(0, "%s: domap failure for create/reload map",
-                               mpp->alias);
+                       condlog(0, "%s: domap (%u) failure "
+                                  "for create/reload map",
+                               mpp->alias, r);
                        remove_map(mpp, vecs, NULL, 0);
                        continue;
                }
-               else if (r < 0)
+               else if (r < 0) {
+                       condlog(0, "%s: domap (%u) failure "
+                                  "for create/reload map",
+                               mpp->alias, r);
                        return r;
+               }
 
                if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
                        if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
index 24c022d..d58d0f9 100644 (file)
@@ -2,8 +2,10 @@
  * configurator actions
  */
 #define ACT_NOTHING_STR         "unchanged"
+#define ACT_REJECT_STR          "reject"
 #define ACT_RELOAD_STR          "reload"
 #define ACT_SWITCHPG_STR        "switchpg"
+#define ACT_RENAME_STR          "rename"
 #define ACT_CREATE_STR          "create"
 
 enum actions {
@@ -12,6 +14,7 @@ enum actions {
        ACT_REJECT,
        ACT_RELOAD,
        ACT_SWITCHPG,
+       ACT_RENAME,
        ACT_CREATE
 };
 
index ab291ae..0f190af 100644 (file)
@@ -387,7 +387,7 @@ dm_flush_map (char * mapname, char * type)
        if (!dm_map_present(mapname))
                return 0;
 
-       if (!dm_type(mapname, type))
+       if (dm_type(mapname, type) <= 0)
                return 1;
 
        if (dm_remove_partmaps(mapname))
@@ -568,7 +568,7 @@ dm_get_maps (vector mp, char * type)
        do {
                info = dm_type(names->name, type);
 
-               if (!info)
+               if (info <= 0)
                        goto next;
 
                mpp = alloc_multipath();
@@ -610,6 +610,35 @@ out:
        return r;
 }
 
+extern int
+dm_get_name(char *uuid, char *type, char *name)
+{
+       vector vec;
+       struct multipath *mpp;
+       int i;
+
+       vec = vector_alloc();
+
+       if (!vec)
+               return 0;
+
+       if (dm_get_maps(vec, type)) {
+               vector_free(vec);
+               return 0;
+       }
+
+       vector_foreach_slot(vec, mpp, i) {
+               if (!strcmp(uuid, mpp->wwid)) {
+                       vector_free(vec);
+                       strcpy(name, mpp->alias);
+                       return 1;
+               }
+       }
+
+       vector_free(vec);
+       return 0;
+}
+
 int
 dm_geteventnr (char *name)
 {
@@ -724,7 +753,7 @@ dm_remove_partmaps (char * mapname)
                    /*
                     * if devmap target is "linear"
                     */
-                   dm_type(names->name, "linear") &&
+                   (dm_type(names->name, "linear") > 0) &&
 
                    /*
                     * and the multipath mapname and the part mapname start
@@ -812,7 +841,6 @@ out:
        return r;
 }
 
-#if 0
 int
 dm_rename (char * old, char * new)
 {
@@ -838,4 +866,3 @@ out:
        dm_task_destroy(dmt);
        return r;
 }
-#endif
index 48b05ec..c7879a7 100644 (file)
@@ -23,7 +23,5 @@ char * dm_mapname(int major, int minor);
 int dm_remove_partmaps (char * mapname);
 int dm_get_uuid(char *name, char *uuid);
 int dm_get_info (char * mapname, struct dm_info ** dmi);
-
-#if 0
 int dm_rename (char * old, char * new);
-#endif
+int dm_get_name(char * uuid, char * type, char * name);
index 267db5a..75d40d9 100644 (file)
@@ -12,6 +12,7 @@
 #include "structs.h"
 #include "config.h"
 #include "debug.h"
+#include "structs_vec.h"
 
 struct path *
 alloc_path (void)
@@ -164,6 +165,14 @@ free_multipath (struct multipath * mpp, int free_paths)
        if (mpp->dmi)
                FREE(mpp->dmi);
        
+#if DAEMON
+       /*
+        * better own vecs->lock here
+        */
+       if (mpp->waiter)
+               ((struct event_thread *)mpp->waiter)->mpp = NULL;
+#endif
+
        free_pathvec(mpp->paths, free_paths);
        free_pgvec(mpp->pg, free_paths);
        FREE(mpp);
index fa5fbad..cd8946f 100644 (file)
@@ -113,6 +113,7 @@ typedef int (pgpolicyfn) (struct multipath *);
 
 struct multipath {
        char wwid[WWID_SIZE];
+       char alias_old[WWID_SIZE];
        int pgpolicy;
        pgpolicyfn *pgpolicyfn;
        int nextpg;
index e7ba68a..99d8512 100644 (file)
@@ -3,6 +3,7 @@
 #include <unistd.h>
 
 #include "vector.h"
+#include "defaults.h"
 #include "debug.h"
 #include "structs.h"
 #include "structs_vec.h"
@@ -241,15 +242,34 @@ set_no_path_retry(struct multipath *mpp)
 extern int
 setup_multipath (struct vectors * vecs, struct multipath * mpp)
 {
+retry:
        if (dm_get_info(mpp->alias, &mpp->dmi))
                goto out;
 
        set_multipath_wwid(mpp);
        mpp->mpe = find_mpe(mpp->wwid);
-       condlog(4, "discovered map %s", mpp->alias);
+       condlog(3, "discovered map %s", mpp->alias);
 
-       if (update_multipath_strings(mpp, vecs->pathvec))
+       if (update_multipath_strings(mpp, vecs->pathvec)) {
+               char new_alias[WWID_SIZE];
+
+               /*
+                * detect an external rename of the multipath device
+                */
+               if (dm_get_name(mpp->wwid, DEFAULT_TARGET, new_alias)) {
+                       condlog(3, "%s multipath mapped device name has "
+                               "changed from %s to %s", mpp->wwid,
+                               mpp->alias, new_alias);
+                       strcpy(mpp->alias, new_alias);
+#if DAEMON
+                       if (mpp->waiter) 
+                               strncpy(((struct event_thread *)mpp->waiter)->mapname,
+                                       new_alias, WWID_SIZE);
+#endif
+                       goto retry;
+               }
                goto out;
+       }
 
        //adopt_paths(vecs->pathvec, mpp);
        mpp->hwe = extract_hwe_from_path(mpp);
index f37e8ab..9b75e9c 100644 (file)
@@ -9,6 +9,17 @@ struct vectors {
        vector mpvec;
 };
 
+#if DAEMON
+struct event_thread {
+       struct dm_task *dmt;
+       pthread_t thread;
+       int event_nr;
+       char mapname[WWID_SIZE];
+       struct vectors *vecs;
+       struct multipath *mpp;
+};
+#endif
+
 typedef void (stop_waiter_thread_func) (struct multipath *, struct vectors *);
 typedef int (start_waiter_thread_func) (struct multipath *, struct vectors *);
 
index 329b46b..b824d39 100644 (file)
@@ -91,14 +91,6 @@ pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
  */
 struct vectors * gvecs; /* global copy of vecs for use in sig handlers */
 
-struct event_thread {
-       struct dm_task *dmt;
-       pthread_t thread;
-       int event_nr;
-       char mapname[WWID_SIZE];
-       struct vectors *vecs;
-};
-
 static struct event_thread *
 alloc_waiter (void)
 {
@@ -115,8 +107,24 @@ free_waiter (void * data)
 {
        struct event_thread * wp = (struct event_thread *)data;
 
+       /*
+        * indicate in mpp that the wp is already freed storage
+        */
+       lock(wp->vecs->lock);
+
+       if (wp->mpp)
+               /*
+                * be careful, mpp may already be freed -- null if so
+                */
+               wp->mpp->waiter = NULL;
+       else
+               condlog(3, "free_waiter, mpp freed before wp=%p,", wp);
+
+       unlock(wp->vecs->lock);
+
        if (wp->dmt)
                dm_task_destroy(wp->dmt);
+
        FREE(wp);
 }
 
@@ -450,6 +458,7 @@ start_waiter_thread (struct multipath * mpp, struct vectors * vecs)
        mpp->waiter = (void *)wp;
        strncpy(wp->mapname, mpp->alias, WWID_SIZE);
        wp->vecs = vecs;
+       wp->mpp = mpp;
 
        if (pthread_create(&wp->thread, &attr, waitevent, wp)) {
                condlog(0, "%s: cannot create event checker", wp->mapname);
@@ -508,7 +517,7 @@ uev_add_map (char * devname, struct vectors * vecs)
        if (!alias)
                return 1;
        
-       if (!dm_type(alias, DEFAULT_TARGET)) {
+       if (dm_type(alias, DEFAULT_TARGET) <= 0) {
                condlog(4, "%s: not a multipath map", alias);
                FREE(alias);
                return 0;
@@ -914,12 +923,9 @@ map_discovery (struct vectors * vecs)
        if (dm_get_maps(vecs->mpvec, "multipath"))
                return 1;
 
-       vector_foreach_slot (vecs->mpvec, mpp, i) {
+       vector_foreach_slot (vecs->mpvec, mpp, i)
                if (setup_multipath(vecs, mpp))
                        return 1;
-               if (start_waiter_thread(mpp, vecs))
-                       return 1;
-       }
 
        return 0;
 }
@@ -994,12 +1000,10 @@ uev_trigger (struct uevent * uev, void * trigger_data)
                        r = uev_add_map(devname, vecs);
                        goto out;
                }
-#if 0
                if (!strncmp(uev->action, "remove", 6)) {
                        r = uev_remove_map(devname, vecs);
                        goto out;
                }
-#endif
                goto out;
        }