[multipathd] add "show wildcards" cli command
[platform/upstream/multipath-tools.git] / multipathd / main.c
index d30ba83..84fb5c4 100644 (file)
@@ -45,6 +45,7 @@
 #include <switchgroup.h>
 #include <print.h>
 #include <configure.h>
+#include <prio.h>
 
 #include "main.h"
 #include "pidfile.h"
@@ -64,6 +65,8 @@
 pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
 pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+int logsink;
+
 /*
  * global copy of vecs for use in sig handlers
  */
@@ -118,7 +121,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
                         * remove all current maps not allowed by the
                         * current configuration
                         */
-                       if (dm_flush_map(ompp->alias, DEFAULT_TARGET)) {
+                       if (dm_flush_map(ompp->alias)) {
                                condlog(0, "%s: unable to flush devmap",
                                        ompp->alias);
                                /*
@@ -137,7 +140,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
                        }
                        else {
                                dm_lib_release();
-                               condlog(3, "%s devmap removed", ompp->alias);
+                               condlog(2, "%s devmap removed", ompp->alias);
                        }
                }
        }
@@ -151,9 +154,13 @@ sync_map_state(struct multipath *mpp)
        struct path *pp;
        unsigned int i, j;
 
+       if (!mpp->pg)
+               return;
+
        vector_foreach_slot (mpp->pg, pgp, i){
                vector_foreach_slot (pgp->paths, pp, j){
-                       if (pp->state <= PATH_UNCHECKED)
+                       if (pp->state == PATH_UNCHECKED || 
+                           pp->state == PATH_WILD)
                                continue;
                        if ((pp->dmstate == PSTATE_FAILED ||
                             pp->dmstate == PSTATE_UNDEF) &&
@@ -185,7 +192,7 @@ flush_map(struct multipath * mpp, struct vectors * vecs)
         * clear references to this map before flushing so we can ignore
         * the spurious uevent we may generate with the dm_flush_map call below
         */
-       if (dm_flush_map(mpp->alias, DEFAULT_TARGET)) {
+       if (dm_flush_map(mpp->alias)) {
                /*
                 * May not really be an error -- if the map was already flushed
                 * from the device mapper by dmsetup(8) for instance.
@@ -195,11 +202,11 @@ flush_map(struct multipath * mpp, struct vectors * vecs)
        }
        else {
                dm_lib_release();
-               condlog(3, "%s: devmap removed", mpp->alias);
+               condlog(2, "%s: devmap removed", mpp->alias);
        }
 
        orphan_paths(vecs->pathvec, mpp);
-       remove_map(mpp, vecs, stop_waiter_thread, 1);
+       remove_map_and_stop_waiter(mpp, vecs, 1);
 
        return 0;
 }
@@ -234,7 +241,7 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs)
 
        map_present = dm_map_present(alias);
 
-       if (map_present && dm_type(alias, DEFAULT_TARGET) <= 0) {
+       if (map_present && dm_type(alias, TGT_MPATH) <= 0) {
                condlog(4, "%s: not a multipath map", alias);
                return 0;
        }
@@ -255,21 +262,20 @@ ev_add_map (struct sysfs_device * dev, struct vectors * vecs)
        /*
         * now we can register the map
         */
-       if (map_present && (mpp = add_map_without_path(vecs, minor, alias,
-                                       start_waiter_thread))) {
+       if (map_present && (mpp = add_map_without_path(vecs, minor, alias))) {
                sync_map_state(mpp);
-               condlog(3, "%s: devmap %s added", alias, dev->kernel);
+               condlog(2, "%s: devmap %s added", alias, dev->kernel);
                return 0;
        }
        refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec);
 
        if (refwwid) {
-               r = coalesce_paths(vecs, NULL, refwwid);
+               r = coalesce_paths(vecs, NULL, refwwid, 0);
                dm_lib_release();
        }
 
        if (!r)
-               condlog(3, "%s: devmap %s added", alias, dev->kernel);
+               condlog(2, "%s: devmap %s added", alias, dev->kernel);
        else
                condlog(0, "%s: uev_add_map %s failed", alias, dev->kernel);
 
@@ -292,7 +298,7 @@ ev_remove_map (char * devname, struct vectors * vecs)
        mpp = find_mp_by_str(vecs->mpvec, devname);
 
        if (!mpp) {
-               condlog(3, "%s: devmap not registered, can't remove",
+               condlog(2, "%s: devmap not registered, can't remove",
                        devname);
                return 0;
        }
@@ -433,11 +439,11 @@ rescan:
            start_waiter_thread(mpp, vecs))
                        goto out;
 
-       condlog(3, "%s path added to devmap %s", devname, mpp->alias);
+       condlog(2, "%s path added to devmap %s", devname, mpp->alias);
        return 0;
 
 out:
-       remove_map(mpp, vecs, NULL, 1);
+       remove_map(mpp, vecs, 1);
        return 1;
 }
 
@@ -459,8 +465,7 @@ ev_remove_path (char * devname, struct vectors * vecs)
 {
        struct multipath * mpp;
        struct path * pp;
-       int i;
-       int rm_path = 1;
+       int i, retval = 0;
 
        pp = find_path_by_dev(vecs->pathvec, devname);
 
@@ -470,100 +475,81 @@ ev_remove_path (char * devname, struct vectors * vecs)
        }
 
        /*
-        * avoid referring to the map of an orphanned path
+        * avoid referring to the map of an orphaned path
         */
        if ((mpp = pp->mpp)) {
+               /*
+                * transform the mp->pg vector of vectors of paths
+                * into a mp->params string to feed the device-mapper
+                */
+               if (update_mpp_paths(mpp, vecs->pathvec)) {
+                       condlog(0, "%s: failed to update paths",
+                               mpp->alias);
+                       goto out;
+               }
+               if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
+                       vector_del_slot(mpp->paths, i);
 
                /*
                 * remove the map IFF removing the last path
                 */
-               if (pathcount(mpp, PATH_WILD) > 1) {
-                       vector rpvec = vector_alloc();
+               if (VECTOR_SIZE(mpp->paths) == 0) {
+                       char alias[WWID_SIZE];
 
                        /*
-                        * transform the mp->pg vector of vectors of paths
-                        * into a mp->params string to feed the device-mapper
+                        * flush_map will fail if the device is open
                         */
-                       update_mpp_paths(mpp, vecs->pathvec);
-                       if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
-                               vector_del_slot(mpp->paths, i);
-
-                       if (VECTOR_SIZE(mpp->paths) == 0) {
-                               char alias[WWID_SIZE];
-
-                               /*
-                                * flush_map will fail if the device is open
-                                */
-                               strncpy(alias, mpp->alias, WWID_SIZE);
-                               if (flush_map(mpp, vecs))
-                                       rm_path = 0;
-                               else
-                                       condlog(3, "%s: removed map after removing"
-                                               " multiple paths", alias);
-                       }
-                       else {
-                               if (setup_map(mpp)) {
-                                       condlog(0, "%s: failed to setup map for"
-                                               " removal of path %s", mpp->alias, devname);
-                                       free_pathvec(rpvec, KEEP_PATHS);
-                                       goto out;
-                               }
-                               /*
-                                * reload the map
-                                */
-                               mpp->action = ACT_RELOAD;
-                               if (domap(mpp) <= 0) {
-                                       condlog(0, "%s: failed in domap for "
-                                               "removal of path %s",
-                                               mpp->alias, devname);
-                                       /*
-                                        * Delete path from pathvec so that
-                                        * update_mpp_paths wont find it later
-                                        * when/if another path is removed.
-                                        */
-                                       if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
-                                               vector_del_slot(vecs->pathvec, i);
-                                       free_path(pp);
-                                       return 1;
-                               }
-                               /*
-                                * update our state from kernel
-                                */
-                               if (setup_multipath(vecs, mpp)) {
-                                       free_pathvec(rpvec, KEEP_PATHS);
-                                       goto out;
-                               }
-                               sync_map_state(mpp);
-
-                               condlog(3, "%s: path removed from map %s",
-                                       devname, mpp->alias);
+                       strncpy(alias, mpp->alias, WWID_SIZE);
+                       if (!flush_map(mpp, vecs)) {
+                               condlog(2, "%s: removed map after"
+                                       " removing all paths",
+                                       alias);
+                               free_path(pp);
+                               return 0;
                        }
-                       free_pathvec(rpvec, KEEP_PATHS);
+                       /*
+                        * Not an error, continue
+                        */
                }
-               else {
-                       char alias[WWID_SIZE];
 
+               if (setup_map(mpp)) {
+                       condlog(0, "%s: failed to setup map for"
+                               " removal of path %s", mpp->alias,
+                               devname);
+                       goto out;
+               }
+               /*
+                * reload the map
+                */
+               mpp->action = ACT_RELOAD;
+               if (domap(mpp) <= 0) {
+                       condlog(0, "%s: failed in domap for "
+                               "removal of path %s",
+                               mpp->alias, devname);
+                       retval = 1;
+               } else {
                        /*
-                        * flush_map will fail if the device is open
+                        * update our state from kernel
                         */
-                       strncpy(alias, mpp->alias, WWID_SIZE);
-                       if (flush_map(mpp, vecs))
-                               rm_path = 0;
-                       else
-                               condlog(3, "%s: removed map", alias);
+                       if (setup_multipath(vecs, mpp)) {
+                               goto out;
+                       }
+                       sync_map_state(mpp);
+
+                       condlog(2, "%s: path removed from map %s",
+                               devname, mpp->alias);
                }
        }
 
-       if (rm_path) {
-               if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
-                       vector_del_slot(vecs->pathvec, i);
-               free_path(pp);
-       }
+       if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
+               vector_del_slot(vecs->pathvec, i);
 
-       return 0;
+       free_path(pp);
+
+       return retval;
 
 out:
-       remove_map(mpp, vecs, stop_waiter_thread, 1);
+       remove_map_and_stop_waiter(mpp, vecs, 1);
        return 1;
 }
 
@@ -573,7 +559,7 @@ map_discovery (struct vectors * vecs)
        struct multipath * mpp;
        unsigned int i;
 
-       if (dm_get_maps(vecs->mpvec, "multipath"))
+       if (dm_get_maps(vecs->mpvec))
                return 1;
 
        vector_foreach_slot (vecs->mpvec, mpp, i)
@@ -706,7 +692,9 @@ uxlsnrloop (void * ap)
                return NULL;
 
        set_handler_callback(LIST+PATHS, cli_list_paths);
+       set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
        set_handler_callback(LIST+MAPS, cli_list_maps);
+       set_handler_callback(LIST+STATUS, cli_list_status);
        set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
        set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
        set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
@@ -715,6 +703,7 @@ uxlsnrloop (void * ap)
        set_handler_callback(LIST+CONFIG, cli_list_config);
        set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
        set_handler_callback(LIST+DEVICES, cli_list_devices);
+       set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
        set_handler_callback(ADD+PATH, cli_add_path);
        set_handler_callback(DEL+PATH, cli_del_path);
        set_handler_callback(ADD+MAP, cli_add_map);
@@ -811,7 +800,7 @@ mpvec_garbage_collector (struct vectors * vecs)
        vector_foreach_slot (vecs->mpvec, mpp, i) {
                if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
                        condlog(2, "%s: remove dead map", mpp->alias);
-                       remove_map(mpp, vecs, stop_waiter_thread, 1);
+                       remove_map_and_stop_waiter(mpp, vecs, 1);
                        i--;
                }
        }
@@ -1021,12 +1010,15 @@ checkerloop (void *ap)
                lock(vecs->lock);
                condlog(4, "tick");
 
-               vector_foreach_slot (vecs->pathvec, pp, i) {
-                       check_path(vecs, pp);
+               if (vecs->pathvec) {
+                       vector_foreach_slot (vecs->pathvec, pp, i) {
+                               check_path(vecs, pp);
+                       }
+               }
+               if (vecs->mpvec) {
+                       defered_failback_tick(vecs->mpvec);
+                       retry_count_tick(vecs->mpvec);
                }
-               defered_failback_tick(vecs->mpvec);
-               retry_count_tick(vecs->mpvec);
-
                if (count)
                        count--;
                else {
@@ -1078,7 +1070,7 @@ configure (struct vectors * vecs, int start_waiters)
        /*
         * create new set of maps & push changed ones into dm
         */
-       if (coalesce_paths(vecs, mpvec, NULL))
+       if (coalesce_paths(vecs, mpvec, NULL, 0))
                return 1;
 
        /*
@@ -1095,7 +1087,7 @@ configure (struct vectors * vecs, int start_waiters)
        /*
         * purge dm of old maps
         */
-       remove_maps(vecs, NULL);
+       remove_maps(vecs);
 
        /*
         * save new set of maps formed by considering current path state
@@ -1125,7 +1117,7 @@ reconfigure (struct vectors * vecs)
         * free old map and path vectors ... they use old conf state
         */
        if (VECTOR_SIZE(vecs->mpvec))
-               remove_maps(vecs, stop_waiter_thread);
+               remove_maps_and_stop_waiters(vecs);
 
        if (VECTOR_SIZE(vecs->pathvec))
                free_pathvec(vecs->pathvec, FREE_PATHS);
@@ -1275,6 +1267,15 @@ child (void * param)
        if (load_config(DEFAULT_CONFIGFILE))
                exit(1);
 
+       if (init_checkers()) {
+               condlog(0, "failed to initialize checkers");
+               exit(1);
+       }
+       if (init_prio()) {
+               condlog(0, "failed to initialize prioritizers");
+               exit(1);
+       }
+
        setlogmask(LOG_UPTO(conf->verbosity + 3));
 
        /*
@@ -1344,7 +1345,7 @@ child (void * param)
         * exit path
         */
        lock(vecs->lock);
-       remove_maps(vecs, stop_waiter_thread);
+       remove_maps_and_stop_waiters(vecs);
        free_pathvec(vecs->pathvec, FREE_PATHS);
 
        pthread_cancel(check_thr);
@@ -1365,8 +1366,6 @@ child (void * param)
        vecs->lock = NULL;
        FREE(vecs);
        vecs = NULL;
-       free_config(conf);
-       conf = NULL;
 
        condlog(2, "--------shut down-------");
 
@@ -1376,6 +1375,14 @@ child (void * param)
        dm_lib_release();
        dm_lib_exit();
 
+       /*
+        * Freeing config must be done after condlog() and dm_lib_exit(),
+        * because logging functions like dlog() and dm_write_log()
+        * reference the config.
+        */
+       free_config(conf);
+       conf = NULL;
+
 #ifdef _DEBUG_
        dbg_free_final(NULL);
 #endif