libmultipath: add marginal paths and groups infrastructure
authorBenjamin Marzinski <bmarzins@redhat.com>
Fri, 23 Aug 2019 17:48:46 +0000 (12:48 -0500)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Tue, 1 Oct 2019 19:58:22 +0000 (21:58 +0200)
This commit adds a marginal variable ot the paths and pathgroups structs.
The marginal paths variable can be set by

multipathd path <path> setmarginal

and cleared by

multipathd path <path> unsetmarginal

All of the marginal paths on a multipath device can be cleared by

multipathd map <map> unsetmarginal

Currently, the marginal variable of a pathgroup will not change. This
will be added by a future commit. The marginal state of a path or
pathgroup is printable with the %M wildcard, and is displayed in the
json output.

Reviewed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
libmultipath/print.c
libmultipath/print.h
libmultipath/structs.h
multipathd/cli.c
multipathd/cli.h
multipathd/cli_handlers.c
multipathd/cli_handlers.h
multipathd/main.c

index fc40b0f..907469a 100644 (file)
@@ -502,6 +502,14 @@ snprint_pg_state (char * buff, size_t len, const struct pathgroup * pgp)
        }
 }
 
+static int
+snprint_pg_marginal (char * buff, size_t len, const struct pathgroup * pgp)
+{
+       if (pgp->marginal)
+               return snprintf(buff, len, "marginal");
+       return snprintf(buff, len, "normal");
+}
+
 static int
 snprint_path_size (char * buff, size_t len, const struct path * pp)
 {
@@ -672,6 +680,14 @@ snprint_path_protocol(char * buff, size_t len, const struct path * pp)
        }
 }
 
+int
+snprint_path_marginal(char * buff, size_t len, const struct path * pp)
+{
+       if (pp->marginal)
+               return snprintf(buff, len, "marginal");
+       return snprintf(buff, len, "normal");
+}
+
 struct multipath_data mpd[] = {
        {'n', "name",          0, snprint_name},
        {'w', "uuid",          0, snprint_multipath_uuid},
@@ -713,6 +729,7 @@ struct path_data pd[] = {
        {'p', "pri",           0, snprint_pri},
        {'S', "size",          0, snprint_path_size},
        {'z', "serial",        0, snprint_path_serial},
+       {'M', "marginal_st",   0, snprint_path_marginal},
        {'m', "multipath",     0, snprint_path_mpp},
        {'N', "host WWNN",     0, snprint_host_wwnn},
        {'n', "target WWNN",   0, snprint_tgt_wwnn},
@@ -729,6 +746,7 @@ struct pathgroup_data pgd[] = {
        {'s', "selector",      0, snprint_pg_selector},
        {'p', "pri",           0, snprint_pg_pri},
        {'t', "dm_st",         0, snprint_pg_state},
+       {'M', "marginal_st",   0, snprint_pg_marginal},
        {0, NULL, 0 , NULL}
 };
 
index e2fb865..7e36ec6 100644 (file)
@@ -50,7 +50,8 @@
 #define PRINT_JSON_GROUP     "{\n" \
                             "         \"selector\" : \"%s\",\n" \
                             "         \"pri\" : %p,\n" \
-                            "         \"dm_st\" : \"%t\","
+                            "         \"dm_st\" : \"%t\",\n" \
+                            "         \"marginal_st\" : \"%M\","
 
 #define PRINT_JSON_GROUP_NUM "         \"group\" : %d,\n"
 
@@ -66,7 +67,8 @@
                             "            \"target_wwnn\" : \"%n\",\n" \
                             "            \"host_wwpn\" : \"%R\",\n" \
                             "            \"target_wwpn\" : \"%r\",\n" \
-                            "            \"host_adapter\" : \"%a\""
+                            "            \"host_adapter\" : \"%a\",\n" \
+                            "            \"marginal_st\" : \"%M\""
 
 #define MAX_LINE_LEN  80
 #define MAX_LINES     64
index 7879d76..1a3d827 100644 (file)
@@ -289,6 +289,7 @@ struct path {
        int io_err_pathfail_cnt;
        int io_err_pathfail_starttime;
        int find_multipaths_timeout;
+       int marginal;
        /* configlet pointers */
        vector hwe;
        struct gen_path generic_path;
@@ -403,6 +404,7 @@ struct pathgroup {
        int status;
        int priority;
        int enabled_paths;
+       int marginal;
        vector paths;
        struct multipath *mpp;
        struct gen_pathgroup generic_pg;
index 17795b6..800c0fb 100644 (file)
@@ -215,6 +215,8 @@ load_keys (void)
        r += add_key(keys, "unsetprkey", UNSETPRKEY, 0);
        r += add_key(keys, "key", KEY, 1);
        r += add_key(keys, "local", LOCAL, 0);
+       r += add_key(keys, "setmarginal", SETMARGINAL, 0);
+       r += add_key(keys, "unsetmarginal", UNSETMARGINAL, 0);
 
 
        if (r) {
@@ -589,6 +591,9 @@ cli_init (void) {
        add_handler(UNSETPRKEY+MAP, NULL);
        add_handler(FORCEQ+DAEMON, NULL);
        add_handler(RESTOREQ+DAEMON, NULL);
+       add_handler(SETMARGINAL+PATH, NULL);
+       add_handler(UNSETMARGINAL+PATH, NULL);
+       add_handler(UNSETMARGINAL+MAP, NULL);
 
        return 0;
 }
index 32dcffa..fdfb9ae 100644 (file)
@@ -45,6 +45,8 @@ enum {
        __UNSETPRKEY,
        __KEY,
        __LOCAL,
+       __SETMARGINAL,
+       __UNSETMARGINAL,
 };
 
 #define LIST           (1 << __LIST)
@@ -89,6 +91,8 @@ enum {
 #define UNSETPRKEY     (1ULL << __UNSETPRKEY)
 #define KEY            (1ULL << __KEY)
 #define LOCAL          (1ULL << __LOCAL)
+#define SETMARGINAL    (1ULL << __SETMARGINAL)
+#define UNSETMARGINAL  (1ULL << __UNSETMARGINAL)
 
 #define INITIAL_REPLY_LEN      1200
 
index 4c32d95..8a89904 100644 (file)
@@ -1537,3 +1537,94 @@ cli_setprkey(void * v, char ** reply, int * len, void * data)
 
        return ret;
 }
+
+int cli_set_marginal(void * v, char ** reply, int * len, void * data)
+{
+       struct vectors * vecs = (struct vectors *)data;
+       char * param = get_keyparam(v, PATH);
+       struct path * pp;
+
+       param = convert_dev(param, 1);
+       pp = find_path_by_dev(vecs->pathvec, param);
+
+       if (!pp)
+               pp = find_path_by_devt(vecs->pathvec, param);
+
+       if (!pp || !pp->mpp || !pp->mpp->alias)
+               return 1;
+
+       condlog(2, "%s: set marginal path %s (operator)",
+               pp->mpp->alias, pp->dev_t);
+       if (pp->mpp->wait_for_udev) {
+               condlog(2, "%s: device not fully created, failing set marginal",
+                       pp->mpp->alias);
+               return 1;
+       }
+       pp->marginal = 1;
+
+       return update_path_groups(pp->mpp, vecs, 0);
+}
+
+int cli_unset_marginal(void * v, char ** reply, int * len, void * data)
+{
+       struct vectors * vecs = (struct vectors *)data;
+       char * param = get_keyparam(v, PATH);
+       struct path * pp;
+
+       param = convert_dev(param, 1);
+       pp = find_path_by_dev(vecs->pathvec, param);
+
+       if (!pp)
+               pp = find_path_by_devt(vecs->pathvec, param);
+
+       if (!pp || !pp->mpp || !pp->mpp->alias)
+               return 1;
+
+       condlog(2, "%s: unset marginal path %s (operator)",
+               pp->mpp->alias, pp->dev_t);
+       if (pp->mpp->wait_for_udev) {
+               condlog(2, "%s: device not fully created, "
+                       "failing unset marginal", pp->mpp->alias);
+               return 1;
+       }
+       pp->marginal = 0;
+
+       return update_path_groups(pp->mpp, vecs, 0);
+}
+
+int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data)
+{
+       struct vectors * vecs = (struct vectors *)data;
+       char * mapname = get_keyparam(v, MAP);
+       struct multipath *mpp;
+       struct pathgroup * pgp;
+       struct path * pp;
+       unsigned int i, j;
+       int minor;
+
+       mapname = convert_dev(mapname, 0);
+       condlog(2, "%s: unset all marginal paths (operator)",
+               mapname);
+
+       if (sscanf(mapname, "dm-%d", &minor) == 1)
+               mpp = find_mp_by_minor(vecs->mpvec, minor);
+       else
+               mpp = find_mp_by_alias(vecs->mpvec, mapname);
+
+       if (!mpp) {
+               condlog(0, "%s: invalid map name. "
+                       "cannot unset marginal paths", mapname);
+               return 1;
+       }
+       if (mpp->wait_for_udev) {
+               condlog(2, "%s: device not fully created, "
+                       "failing unset all marginal", mpp->alias);
+               return 1;
+       }
+
+       vector_foreach_slot (mpp->pg, pgp, i)
+               vector_foreach_slot (pgp->paths, pp, j)
+                       pp->marginal = 0;
+
+       return update_path_groups(mpp, vecs, 0);
+}
index edbdf06..0f45106 100644 (file)
@@ -49,3 +49,6 @@ int cli_unsetprstatus(void * v, char ** reply, int * len, void * data);
 int cli_getprkey(void * v, char ** reply, int * len, void * data);
 int cli_setprkey(void * v, char ** reply, int * len, void * data);
 int cli_unsetprkey(void * v, char ** reply, int * len, void * data);
+int cli_set_marginal(void * v, char ** reply, int * len, void * data);
+int cli_unset_marginal(void * v, char ** reply, int * len, void * data);
+int cli_unset_all_marginal(void * v, char ** reply, int * len, void * data);
index 7a5cd11..7db1573 100644 (file)
@@ -1609,6 +1609,9 @@ uxlsnrloop (void * ap)
        set_handler_callback(GETPRKEY+MAP, cli_getprkey);
        set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey);
        set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey);
+       set_handler_callback(SETMARGINAL+PATH, cli_set_marginal);
+       set_handler_callback(UNSETMARGINAL+PATH, cli_unset_marginal);
+       set_handler_callback(UNSETMARGINAL+MAP, cli_unset_all_marginal);
 
        umask(077);
        uxsock_listen(&uxsock_trigger, ux_sock, ap);