multipathd: use foreign API
authorMartin Wilck <mwilck@suse.com>
Mon, 5 Mar 2018 23:15:04 +0000 (00:15 +0100)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Wed, 7 Mar 2018 09:40:09 +0000 (10:40 +0100)
Call into the foreign library code when paths are discovered, uevents
are received, and in the checker loop. Furthermore, use the foreign
code to print information in the "multipathd show paths", "multipathd
show maps", and "multipathd show topology" client commands.

We don't support foreign data in the individual "show map" and "show path"
commands, and neither in the "json" commands. The former is a deliberate
decision, the latter could be added if desired.

Signed-off-by: Martin Wilck <mwilck@suse.com>
multipathd/cli_handlers.c
multipathd/main.c

index 0658fb9..898c163 100644 (file)
@@ -27,6 +27,7 @@
 #include "main.h"
 #include "cli.h"
 #include "uevent.h"
+#include "foreign.h"
 
 int
 show_paths (char ** r, int * len, struct vectors * vecs, char * style,
@@ -35,11 +36,13 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style,
        int i;
        struct path * pp;
        char * c;
-       char * reply;
+       char * reply, * header;
        unsigned int maxlen = INITIAL_REPLY_LEN;
        int again = 1;
 
        get_path_layout(vecs->pathvec, 1);
+       foreign_path_layout();
+
        reply = MALLOC(maxlen);
 
        while (again) {
@@ -48,18 +51,29 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style,
 
                c = reply;
 
-               if (pretty && VECTOR_SIZE(vecs->pathvec) > 0)
+               if (pretty)
                        c += snprint_path_header(c, reply + maxlen - c,
                                                 style);
+               header = c;
 
                vector_foreach_slot(vecs->pathvec, pp, i)
                        c += snprint_path(c, reply + maxlen - c,
                                          style, pp, pretty);
 
+               c += snprint_foreign_paths(c, reply + maxlen - c,
+                                          style, pretty);
+
                again = ((c - reply) == (maxlen - 1));
 
                REALLOC_REPLY(reply, again, maxlen);
        }
+
+       if (pretty && c == header) {
+               /* No output - clear header */
+               *reply = '\0';
+               c = reply;
+       }
+
        *r = reply;
        *len = (int)(c - reply + 1);
        return 0;
@@ -134,6 +148,8 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
        int again = 1;
 
        get_path_layout(vecs->pathvec, 0);
+       foreign_path_layout();
+
        reply = MALLOC(maxlen);
 
        while (again) {
@@ -150,11 +166,13 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
                        c += snprint_multipath_topology(c, reply + maxlen - c,
                                                        mpp, 2);
                }
+               c += snprint_foreign_topology(c, reply + maxlen - c, 2);
 
                again = ((c - reply) == (maxlen - 1));
 
                REALLOC_REPLY(reply, again, maxlen);
        }
+
        *r = reply;
        *len = (int)(c - reply + 1);
        return 0;
@@ -499,12 +517,14 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style,
 {
        int i;
        struct multipath * mpp;
-       char * c;
+       char * c, *header;
        char * reply;
        unsigned int maxlen = INITIAL_REPLY_LEN;
        int again = 1;
 
        get_multipath_layout(vecs->mpvec, 1);
+       foreign_multipath_layout();
+
        reply = MALLOC(maxlen);
 
        while (again) {
@@ -512,9 +532,10 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style,
                        return 1;
 
                c = reply;
-               if (pretty && VECTOR_SIZE(vecs->mpvec) > 0)
+               if (pretty)
                        c += snprint_multipath_header(c, reply + maxlen - c,
                                                      style);
+               header = c;
 
                vector_foreach_slot(vecs->mpvec, mpp, i) {
                        if (update_multipath(vecs, mpp->alias, 0)) {
@@ -523,12 +544,20 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style,
                        }
                        c += snprint_multipath(c, reply + maxlen - c,
                                               style, mpp, pretty);
-               }
 
+               }
+               c += snprint_foreign_multipaths(c, reply + maxlen - c,
+                                               style, pretty);
                again = ((c - reply) == (maxlen - 1));
 
                REALLOC_REPLY(reply, again, maxlen);
        }
+
+       if (pretty && c == header) {
+               /* No output - clear header */
+               *reply = '\0';
+               c = reply;
+       }
        *r = reply;
        *len = (int)(c - reply + 1);
        return 0;
index 5458fa5..9d458dd 100644 (file)
@@ -84,6 +84,7 @@ static int use_watchdog;
 #include "waiter.h"
 #include "io_err_stat.h"
 #include "wwids.h"
+#include "foreign.h"
 #include "../third-party/valgrind/drd.h"
 
 #define FILE_NAME_SIZE 256
@@ -780,6 +781,8 @@ uev_remove_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
        int ret;
 
        condlog(2, "%s: remove path (uevent)", uev->kernel);
+       delete_foreign(uev->udev);
+
        pthread_cleanup_push(cleanup_lock, &vecs->lock);
        lock(&vecs->lock);
        pthread_testcancel();
@@ -899,12 +902,27 @@ fail:
 static int
 uev_update_path (struct uevent *uev, struct vectors * vecs)
 {
-       int ro, retval = 0;
+       int ro, retval = 0, rc;
        struct path * pp;
        struct config *conf;
        int disable_changed_wwids;
        int needs_reinit = 0;
 
+       switch ((rc = change_foreign(uev->udev))) {
+       case FOREIGN_OK:
+               /* known foreign path, ignore event */
+               return 0;
+       case FOREIGN_IGNORED:
+               break;
+       case FOREIGN_ERR:
+               condlog(3, "%s: error in change_foreign", __func__);
+               break;
+       default:
+               condlog(1, "%s: return code %d of change_forein is unsupported",
+                       __func__, rc);
+               break;
+       }
+
        conf = get_multipath_config();
        disable_changed_wwids = conf->disable_changed_wwids;
        put_multipath_config(conf);
@@ -1104,8 +1122,13 @@ uev_trigger (struct uevent * uev, void * trigger_data)
         * are not fully initialised then.
         */
        if (!strncmp(uev->kernel, "dm-", 3)) {
-               if (!uevent_is_mpath(uev))
+               if (!uevent_is_mpath(uev)) {
+                       if (!strncmp(uev->action, "change", 6))
+                               (void)add_foreign(uev->udev);
+                       else if (!strncmp(uev->action, "remove", 6))
+                               (void)delete_foreign(uev->udev);
                        goto out;
+               }
                if (!strncmp(uev->action, "change", 6)) {
                        r = uev_add_map(uev, vecs);
 
@@ -1914,7 +1937,7 @@ checkerloop (void *ap)
                                                diff_time.tv_sec);
                        }
                }
-
+               check_foreign();
                post_config_state(DAEMON_IDLE);
                conf = get_multipath_config();
                strict_timing = conf->strict_timing;
@@ -2101,6 +2124,7 @@ reconfigure (struct vectors * vecs)
 
        free_pathvec(vecs->pathvec, FREE_PATHS);
        vecs->pathvec = NULL;
+       delete_all_foreign();
 
        /* Re-read any timezone changes */
        tzset();
@@ -2354,6 +2378,9 @@ child (void * param)
                condlog(0, "failed to initialize prioritizers");
                goto failed;
        }
+       /* Failing this is non-fatal */
+
+       init_foreign(conf->multipath_dir);
 
        setlogmask(LOG_UPTO(conf->verbosity + 3));
 
@@ -2511,6 +2538,7 @@ child (void * param)
        FREE(vecs);
        vecs = NULL;
 
+       cleanup_foreign();
        cleanup_checkers();
        cleanup_prio();