[libmultipath] blacklist exceptions
authorChristophe Varoqui <cvaroqui@zezette.localdomain>
Sun, 7 Jan 2007 22:53:06 +0000 (23:53 +0100)
committerChristophe Varoqui <cvaroqui@zezette.localdomain>
Sun, 7 Jan 2007 22:53:06 +0000 (23:53 +0100)
On IBM System z we often have the problem that we have attached
several hundred devices. In case we want to use only a few of them
with mp-tools, we have to blacklist all others. For that reason I have
introduced a blacklist_exceptions keyword for the multipath.conf  which
fills an internal exception list.

Additionally this patch adds two commands to the multipathd cli to
display blacklist rules and blacklisted devices.

A multipath.conf like:
------------------- snip --------------------
blacklist {
        devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
        devnode "^hd[a-z][[0-9]*]"
        devnode "^cciss!c[0-9]d[0-9]*[p[0-9]*]"
        devnode "^dasd[a-z]+[0-9]*"
}
blacklist_exceptions {
        devnode "^dasd[c-d]+[0-9]*"
}
------------------- snap --------------------

All DASD devices are blacklisted except dasdc and
dasdd and corresponding partitions, which are listed in
the blacklist:exceptions section.
This example would produce the following output in the
"multipathd -k" cli:

------------------- snip --------------------
multipathd> show blacklist
device node rules:
- blacklist:
        (config file rule) ^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*
        (config file rule) ^hd[a-z][[0-9]*]
        (config file rule) ^cciss!c[0-9]d[0-9]*[p[0-9]*]
        (config file rule) ^dasd[a-z]+[0-9]*
        (default rule)     ^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*
        (default rule)     ^hd[a-z]
        (default rule)     ^cciss!c[0-9]d[0-9]*
- exceptions:
        (config file rule) ^dasd[c-d]+[0-9]*
wwid rules:
- blacklist:
        <empty>
- exceptions:
        <empty>
device rules:
- blacklist:
        (default rule)     DGC:LUNZ
multipathd>

multipathd> show devices
available block devices:
    dasda (blacklisted)
    dasdb (blacklisted)
    dasdc
    dasdd
    dm-0 (blacklisted)
    dm-1 (blacklisted)
    dm-2 (blacklisted)
    dm-3 (blacklisted)
    dm-4 (blacklisted)
    dm-5 (blacklisted)
    dm-6 (blacklisted)
    loop0 (blacklisted)
    loop1 (blacklisted)
    loop2 (blacklisted)
    loop3 (blacklisted)
    loop4 (blacklisted)
    loop5 (blacklisted)
    loop6 (blacklisted)
    loop7 (blacklisted)
    ram0 (blacklisted)
    ram10 (blacklisted)
    ram11 (blacklisted)
    ram12 (blacklisted)
    ram13 (blacklisted)
    ram14 (blacklisted)
    ram15 (blacklisted)
    ram1 (blacklisted)
    ram2 (blacklisted)
    ram3 (blacklisted)
    ram4 (blacklisted)
    ram5 (blacklisted)
    ram6 (blacklisted)
    ram7 (blacklisted)
    ram8 (blacklisted)
    ram9 (blacklisted)
    sda
    sdb
    sdc
    sdd
multipathd>
------------------- snap --------------------

Signed-off-by: Volker Sameske <sameske@de.ibm.com>
17 files changed:
libmultipath/blacklist.c
libmultipath/blacklist.h
libmultipath/config.c
libmultipath/config.h
libmultipath/dict.c
libmultipath/discovery.c
libmultipath/print.c
libmultipath/print.h
multipath.conf.annotated
multipath.conf.synthetic
multipath/main.c
multipathd/cli.c
multipathd/cli.h
multipathd/cli_handlers.c
multipathd/cli_handlers.h
multipathd/main.c
multipathd/multipathd.8

index 6a8a681..5cd60a1 100644 (file)
@@ -2,7 +2,6 @@
  * Copyright (c) 2004, 2005 Christophe Varoqui
  */
 #include <stdio.h>
-
 #include <checkers.h>
 
 #include "memory.h"
@@ -14,7 +13,7 @@
 #include "blacklist.h"
 
 extern int
-store_ble (vector blist, char * str)
+store_ble (vector blist, char * str, int origin)
 {
        struct blentry * ble;
        
@@ -36,6 +35,7 @@ store_ble (vector blist, char * str)
                goto out1;
 
        ble->str = str;
+       ble->origin = origin;
        vector_set_slot(blist, ble);
        return 0;
 out1:
@@ -63,7 +63,7 @@ alloc_ble_device (vector blist)
 }
        
 extern int
-set_ble_device (vector blist, char * vendor, char * product)
+set_ble_device (vector blist, char * vendor, char * product, int origin)
 {
        struct blentry_device * ble;
        
@@ -91,6 +91,7 @@ set_ble_device (vector blist, char * vendor, char * product)
                }
                ble->product = product;
        }
+       ble->origin = origin;
        return 0;
 }
 
@@ -105,19 +106,19 @@ setup_default_blist (struct config * conf)
        str = STRDUP("^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*");
        if (!str)
                return 1;
-       if (store_ble(conf->blist_devnode, str))
+       if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
                return 1;
 
        str = STRDUP("^hd[a-z]");
        if (!str)
                return 1;
-       if (store_ble(conf->blist_devnode, str))
+       if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
                return 1;
        
        str = STRDUP("^cciss!c[0-9]d[0-9]*");
        if (!str)
                return 1;
-       if (store_ble(conf->blist_devnode, str))
+       if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
                return 1;
 
        vector_foreach_slot (conf->hwtable, hwe, i) {
@@ -128,7 +129,8 @@ setup_default_blist (struct config * conf)
                                          VECTOR_SIZE(conf->blist_device) -1);
                        if (set_ble_device(conf->blist_device,
                                           STRDUP(hwe->vendor),
-                                          STRDUP(hwe->bl_product))) {
+                                          STRDUP(hwe->bl_product),
+                                          ORIGIN_DEFAULT)) {
                                FREE(ble);
                                return 1;
                        }
@@ -139,11 +141,29 @@ setup_default_blist (struct config * conf)
 }
 
 int
-blacklist (vector blist, char * str)
+blacklist_exceptions (vector elist, char * str)
+{
+        int i;
+        struct blentry * ele;
+
+        vector_foreach_slot (elist, ele, i) {
+                if (!regexec(&ele->regex, str, 0, NULL, 0)) {
+                       condlog(3, "%s: exception-listed", str);
+                       return 1;
+               }
+       }
+        return 0;
+}
+
+int
+blacklist (vector blist, vector elist, char * str)
 {
        int i;
        struct blentry * ble;
 
+       if (blacklist_exceptions(elist, str))
+               return 0;
+
        vector_foreach_slot (blist, ble, i) {
                if (!regexec(&ble->regex, str, 0, NULL, 0)) {
                        condlog(3, "%s: blacklisted", str);
@@ -172,10 +192,10 @@ blacklist_device (vector blist, char * vendor, char * product)
 int
 blacklist_path (struct config * conf, struct path * pp)
 {
-       if (blacklist(conf->blist_devnode, pp->dev))
+       if (blacklist(conf->blist_devnode, conf->elist_devnode, pp->dev))
                return 1;
 
-       if (blacklist(conf->blist_wwid, pp->wwid))
+       if (blacklist(conf->blist_wwid, conf->elist_wwid, pp->wwid))
                return 1;
 
        if (pp->vendor_id && pp->product_id &&
index 9e2b63c..104e7fd 100644 (file)
@@ -6,6 +6,7 @@
 struct blentry {
        char * str;
        regex_t regex;
+       int origin;
 };
 
 struct blentry_device {
@@ -13,15 +14,16 @@ struct blentry_device {
        char * product;
        regex_t vendor_reg;
        regex_t product_reg;
+       int origin;
 };
 
 int setup_default_blist (struct config *);
 int alloc_ble_device (vector);
-int blacklist (vector, char *);
+int blacklist (vector, vector, char *);
 int blacklist_device (vector, char *, char *);
 int blacklist_path (struct config *, struct path *);
-int store_ble (vector, char *);
-int set_ble_device (vector, char *, char *);
+int store_ble (vector, char *, int);
+int set_ble_device (vector, char *, char *, int);
 void free_blacklist (vector);
 void free_blacklist_device (vector);
 
index 528e475..b2fdf16 100644 (file)
@@ -333,6 +333,12 @@ free_config (struct config * conf)
        free_blacklist(conf->blist_devnode);
        free_blacklist(conf->blist_wwid);
        free_blacklist_device(conf->blist_device);
+
+       if (conf->elist_devnode)
+               FREE(conf->elist_devnode);
+       if (conf->elist_wwid)
+               FREE(conf->elist_wwid);
+
        free_mptable(conf->mptable);
        free_hwtable(conf->hwtable);
        free_keywords(conf->keywords);
@@ -403,6 +409,19 @@ load_config (char * file)
        if (setup_default_blist(conf))
                goto out;
 
+       if (conf->elist_devnode == NULL) {
+                conf->elist_devnode = vector_alloc();
+
+                if (!conf->elist_devnode)
+                       goto out;
+       }
+       if (conf->elist_wwid == NULL) {
+               conf->elist_wwid = vector_alloc();
+
+                if (!conf->elist_wwid)
+                       goto out;
+       }
+
        if (conf->mptable == NULL) {
                conf->mptable = vector_alloc();
 
index 0c3b640..90380bd 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _CONFIG_H
 #define _CONFIG_H
 
+#define ORIGIN_DEFAULT 0
+#define ORIGIN_CONFIG  1
+
 enum devtypes {
        DEV_NONE,
        DEV_DEVT,
@@ -75,6 +78,8 @@ struct config {
        vector blist_devnode;
        vector blist_wwid;
        vector blist_device;
+       vector elist_devnode;
+       vector elist_wwid;
 };
 
 struct config * conf;
index 9ca228a..e5db4ef 100644 (file)
@@ -237,6 +237,18 @@ blacklist_handler(vector strvec)
        return 0;
 }
 
+static int
+blacklist_exceptions_handler(vector strvec)
+{
+        conf->elist_devnode = vector_alloc();
+        conf->elist_wwid = vector_alloc();
+
+        if (!conf->elist_devnode || !conf->elist_wwid)
+                return 1;
+
+        return 0;
+}
+
 static int
 ble_devnode_handler(vector strvec)
 {
@@ -247,7 +259,20 @@ ble_devnode_handler(vector strvec)
        if (!buff)
                return 1;
 
-       return store_ble(conf->blist_devnode, buff);
+       return store_ble(conf->blist_devnode, buff, ORIGIN_CONFIG);
+}
+
+static int
+ble_except_devnode_handler(vector strvec)
+{
+        char * buff;
+
+        buff = set_value(strvec);
+
+        if (!buff)
+                return 1;
+
+       return store_ble(conf->elist_devnode, buff, ORIGIN_CONFIG);
 }
 
 static int
@@ -260,7 +285,20 @@ ble_wwid_handler(vector strvec)
        if (!buff)
                return 1;
 
-       return store_ble(conf->blist_wwid, buff);
+       return store_ble(conf->blist_wwid, buff, ORIGIN_CONFIG);
+}
+
+static int
+ble_except_wwid_handler(vector strvec)
+{
+        char * buff;
+
+        buff = set_value(strvec);
+
+        if (!buff)
+                return 1;
+
+       return store_ble(conf->elist_wwid, buff, ORIGIN_CONFIG);
 }
 
 static int
@@ -279,7 +317,7 @@ ble_vendor_handler(vector strvec)
        if (!buff)
                return 1;
 
-       return set_ble_device(conf->blist_device, buff, NULL);
+       return set_ble_device(conf->blist_device, buff, NULL, ORIGIN_CONFIG);
 }
 
 static int
@@ -292,7 +330,7 @@ ble_product_handler(vector strvec)
        if (!buff)
                return 1;
 
-       return set_ble_device(conf->blist_device, NULL, buff);
+       return set_ble_device(conf->blist_device, NULL, buff, ORIGIN_CONFIG);
 }
 
 /*
@@ -1336,6 +1374,9 @@ init_keywords(void)
        install_keyword("vendor", &ble_vendor_handler, &snprint_bled_vendor);
        install_keyword("product", &ble_product_handler, &snprint_bled_product);
        install_sublevel_end();
+       install_keyword_root("blacklist_exceptions", &blacklist_exceptions_handler);
+       install_keyword("devnode", &ble_except_devnode_handler, &snprint_ble_simple);
+       install_keyword("wwid", &ble_except_wwid_handler, &snprint_ble_simple);
 
 #if 0
        __deprecated install_keyword_root("devnode_blacklist", &blacklist_handler);
index a4a7997..cf56f9c 100644 (file)
@@ -61,7 +61,7 @@ path_discover (vector pathvec, struct config * conf, char * devname, int flag)
        if (!devname)
                return 0;
 
-       if (blacklist(conf->blist_devnode, devname))
+       if (blacklist(conf->blist_devnode, conf->elist_devnode, devname))
                return 0;
 
        if(safe_sprintf(path, "%s/block/%s/device", sysfs_path,
index 260aed1..dbad281 100644 (file)
@@ -5,6 +5,8 @@
 #include <string.h>
 #include <libdevmapper.h>
 #include <stdarg.h>
+#include <sysfs/dlist.h>
+#include <sysfs/libsysfs.h>
 
 #include <checkers.h>
 
@@ -18,6 +20,7 @@
 #include "pgpolicies.h"
 #include "defaults.h"
 #include "parser.h"
+#include "blacklist.h"
 
 #define MAX(x,y) (x > y) ? x : y
 #define TAIL     (line + len - 1 - c)
@@ -850,6 +853,104 @@ snprint_defaults (char * buff, int len)
        
 }
 
+static int
+snprint_blacklist_group (char *buff, int len, int *fwd, vector *vec)
+{
+       int threshold = MAX_LINE_LEN;
+       struct blentry * ble;
+       int pos;
+       int i;
+
+       pos = *fwd;
+       if (!VECTOR_SIZE(*vec)) {
+               if ((len - pos - threshold) <= 0)
+                       return 0;
+               pos += snprintf(buff + pos, len - pos, "        <empty>\n");
+       } else vector_foreach_slot (*vec, ble, i) {
+               if ((len - pos - threshold) <= 0)
+                       return 0;
+               if (ble->origin == ORIGIN_CONFIG)
+                       pos += snprintf(buff + pos, len - pos, "        (config file rule) ");
+               else if (ble->origin == ORIGIN_DEFAULT)
+                       pos += snprintf(buff + pos, len - pos, "        (default rule)     ");
+               pos += snprintf(buff + pos, len - pos, "%s\n", ble->str);
+       }
+
+       *fwd = pos;
+       return pos;
+}
+
+static int
+snprint_blacklist_devgroup (char *buff, int len, int *fwd, vector *vec)
+{
+       int threshold = MAX_LINE_LEN;
+       struct blentry_device * bled;
+       int pos;
+       int i;
+
+       pos = *fwd;
+       if (!VECTOR_SIZE(*vec)) {
+               if ((len - pos - threshold) <= 0)
+                       return 0;
+               pos += snprintf(buff + pos, len - pos, "        <empty>\n");
+       } else vector_foreach_slot (*vec, bled, i) {
+               if ((len - pos - threshold) <= 0)
+                       return 0;
+               if (bled->origin == ORIGIN_CONFIG)
+                       pos += snprintf(buff + pos, len - pos, "        (config file rule) ");
+               else if (bled->origin == ORIGIN_DEFAULT)
+                       pos += snprintf(buff + pos, len - pos, "        (default rule)     ");
+               pos += snprintf(buff + pos, len - pos, "%s:%s\n", bled->vendor, bled->product);
+       }
+
+       *fwd = pos;
+       return pos;
+}
+
+extern int
+snprint_blacklist_report (char * buff, int len)
+{
+       int threshold = MAX_LINE_LEN;
+       int fwd = 0;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "device node rules:\n"
+                                              "- blacklist:\n");
+       if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_devnode))
+               return len;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n");
+       if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_devnode) == 0)
+               return len;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n"
+                                              "- blacklist:\n");
+       if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0)
+               return len;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n");
+       if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_wwid) == 0)
+               return len;
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "device rules:\n"
+                                              "- blacklist:\n");
+       if (snprint_blacklist_devgroup(buff, len, &fwd, &conf->blist_device) == 0)
+               return len;
+
+       if (fwd > len)
+               return len;
+       return fwd;
+}
+
 extern int
 snprint_blacklist (char * buff, int len)
 {
@@ -912,12 +1013,96 @@ snprint_blacklist (char * buff, int len)
                if (fwd > len)
                        return len;
        }
+       fwd += snprintf(buff + fwd, len - fwd, "}\n");
+       if (fwd > len)
+               return len;
+       return fwd;
+}
 
+extern int
+snprint_blacklist_except (char * buff, int len)
+{
+       int i;
+       struct blentry * ele;
+       int fwd = 0;
+       struct keyword *rootkw;
+       struct keyword *kw;
+
+       rootkw = find_keyword(NULL, "blacklist_exceptions");
+       if (!rootkw)
+               return 0;
+
+       fwd += snprintf(buff + fwd, len - fwd, "blacklist_exceptions {\n");
+       if (fwd > len)
+               return len;
+
+       vector_foreach_slot (conf->elist_devnode, ele, i) {
+               kw = find_keyword(rootkw->sub, "devnode");
+               if (!kw)
+                       return 0;
+               fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+                                      kw, ele);
+               if (fwd > len)
+                       return len;
+       }
+       vector_foreach_slot (conf->elist_wwid, ele, i) {
+               kw = find_keyword(rootkw->sub, "wwid");
+               if (!kw)
+                       return 0;
+               fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
+                                      kw, ele);
+               if (fwd > len)
+                       return len;
+       }
        fwd += snprintf(buff + fwd, len - fwd, "}\n");
        if (fwd > len)
                return len;
        return fwd;
-       
+}
+
+extern int
+snprint_devices (char * buff, int len, struct vectors *vecs)
+{
+        struct dlist * ls;
+        struct sysfs_class * class;
+        struct sysfs_class_device * dev;
+       int threshold = MAX_LINE_LEN;
+       int fwd = 0;
+
+
+       struct path * pp;
+
+
+
+        if (!(class = sysfs_open_class("block")))
+                return 0;
+
+        if (!(ls = sysfs_get_class_devices(class))) {
+                sysfs_close_class(class);
+                return 0;
+        }
+
+       if ((len - fwd - threshold) <= 0)
+               return len;
+       fwd += snprintf(buff + fwd, len - fwd, "available block devices:\n");
+
+        dlist_for_each_data(ls, dev, struct sysfs_class_device) {
+               if ((len - fwd - threshold)  <= 0)
+                       return len;
+               fwd += snprintf(buff + fwd, len - fwd, "    %s ", dev->name);
+               pp = find_path_by_dev(vecs->pathvec, dev->name);
+               if (blacklist(conf->blist_devnode, conf->elist_devnode,
+                             dev->name) || pp == NULL)
+                       fwd += snprintf(buff + fwd, len - fwd,
+                                       "(blacklisted)\n");
+                else
+                       fwd += snprintf(buff + fwd, len - fwd, "\n");
+        }
+        sysfs_close_class(class);
+
+       if (fwd > len)
+               return len;
+       return fwd;
 }
 
 extern int
index 3dde45d..73c2f63 100644 (file)
@@ -42,6 +42,9 @@ int snprint_multipath_topology (char *, int, struct multipath * mpp,
                                int verbosity);
 int snprint_defaults (char *, int);
 int snprint_blacklist (char *, int);
+int snprint_blacklist_except (char *, int);
+int snprint_blacklist_report (char *, int);
+int snprint_devices (char *, int, struct vectors *);
 int snprint_hwtable (char *, int, vector);
 int snprint_mptable (char *, int, vector);
 
index f55c367..649ff8c 100644 (file)
 #               product MSA[15]00
 #       }
 #}
+##
+## name    : blacklist_exceptions
+## scope   : multipath & multipathd
+## desc    : list of device names to be treated as multipath candidates
+##           even if they are on the blacklist.
+##           Note: blacklist exceptions are only valid in the same class.
+##           It is not possible to blacklist devices using the devnode keyword
+##           and to exclude some devices of them using the wwid keyword.
+## default : -
+##
+#blacklist_exceptions {
+#       devnode "^dasd[c-d]+[0-9]*"
+#       wwid    "IBM.75000000092461.4d00.34"
+#       wwid    "IBM.75000000092461.4d00.35"
+#       wwid    "IBM.75000000092461.4d00.36"
+#}
 #
 ##
 ## name    : multipaths
index 4a1f5a4..e5e6cd0 100644 (file)
@@ -16,7 +16,7 @@
 #      no_path_retry           fail
 #      user_friendly_names     no
 #}
-#devnode_blacklist {
+#blacklist {
 #       wwid 26353900f02796769
 #      devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
 #      devnode "^hd[a-z][[0-9]*]"
 #              product MSA[15]00
 #      }
 #}
+#blacklist_exceptions {
+#       devnode "^dasd[c-d]+[0-9]*"
+#       wwid    "IBM.75000000092461.4d00.34"
+#}
 #multipaths {
 #      multipath {
 #              wwid                    3600508b4000156d700012000000b0000
index 62263a9..faccdbb 100644 (file)
@@ -234,7 +234,7 @@ configure (void)
                        dev = conf->dev;
        }
        
-       if (dev && blacklist(conf->blist_devnode, dev))
+       if (dev && blacklist(conf->blist_devnode, conf->elist_devnode, dev))
                goto out;
        
        /*
@@ -250,7 +250,7 @@ configure (void)
                }
                condlog(3, "scope limited to %s", refwwid);
 
-               if (blacklist(conf->blist_wwid, refwwid))
+               if (blacklist(conf->blist_wwid, conf->elist_wwid, refwwid))
                        goto out;
        }
 
index bd0d03b..4edf1af 100644 (file)
@@ -141,6 +141,8 @@ load_keys (void)
        r += add_key(keys, "stats", STATS, 0);
        r += add_key(keys, "topology", TOPOLOGY, 0);
        r += add_key(keys, "config", CONFIG, 0);
+       r += add_key(keys, "blacklist", BLACKLIST, 0);
+       r += add_key(keys, "devices", DEVICES, 0);
 
        if (r) {
                free_keys(keys);
index ef1e3b8..99dfcbd 100644 (file)
@@ -17,6 +17,8 @@ enum {
        __STATS,
        __TOPOLOGY,
        __CONFIG,
+       __BLACKLIST,
+       __DEVICES,
 };
 
 #define LIST           (1 << __LIST)
@@ -37,6 +39,8 @@ enum {
 #define STATS          (1 << __STATS)
 #define TOPOLOGY       (1 << __TOPOLOGY)
 #define CONFIG         (1 << __CONFIG)
+#define BLACKLIST      (1 << __BLACKLIST)
+#define DEVICES        (1 << __DEVICES)
 
 #define INITIAL_REPLY_LEN 1000
 
index b5d8e00..9cd5902 100644 (file)
@@ -143,6 +143,12 @@ show_config (char ** r, int * len)
                        reply = REALLOC(reply, maxlen *= 2);
                        continue;
                }
+               c += snprint_blacklist_except(c, reply + maxlen - c);
+               again = ((c - reply) == maxlen);
+               if (again) {
+                       reply = REALLOC(reply, maxlen *= 2);
+                       continue;
+               }
                c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
                again = ((c - reply) == maxlen);
                if (again) {
@@ -280,7 +286,7 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
 
        condlog(2, "%s: add path (operator)", param);
 
-       if (blacklist(conf->blist_devnode, param) ||
+       if (blacklist(conf->blist_devnode, conf->elist_devnode, param) ||
            (r = ev_add_path(param, vecs)) == 2) {
                *reply = strdup("blacklisted");
                *len = strlen(*reply) + 1;
@@ -309,7 +315,7 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
 
        condlog(2, "%s: add map (operator)", param);
 
-       if (blacklist(conf->blist_wwid, param)) {
+       if (blacklist(conf->blist_wwid, conf->elist_wwid, param)) {
                *reply = strdup("blacklisted");
                *len = strlen(*reply) + 1;
                condlog(2, "%s: map blacklisted", param);
@@ -433,3 +439,79 @@ cli_fail(void * v, char ** reply, int * len, void * data)
 
        return dm_fail_path(pp->mpp->alias, pp->dev_t);
 }
+
+int
+show_blacklist (char ** r, int * len)
+{
+        char *c = NULL;
+        char *reply = NULL;
+        unsigned int maxlen = INITIAL_REPLY_LEN;
+        int again = 1;
+
+        while (again) {
+               reply = MALLOC(maxlen);
+               if (!reply)
+                       return 1;
+
+                c = reply;
+                c += snprint_blacklist_report(c, maxlen);
+                again = ((c - reply) == maxlen);
+                if (again) {
+                       maxlen  *= 2;
+                       FREE(reply);
+                        continue;
+                }
+        }
+
+        *r = reply;
+        *len = (int)(c - reply + 1);
+
+        return 0;
+}
+
+int
+cli_list_blacklist (void * v, char ** reply, int * len, void * data)
+{
+        condlog(3, "list blacklist (operator)");
+
+        return show_blacklist(reply, len);
+}
+
+int
+show_devices (char ** r, int * len, struct vectors *vecs)
+{
+        char *c = NULL;
+        char *reply = NULL;
+        unsigned int maxlen = INITIAL_REPLY_LEN;
+        int again = 1;
+
+        while (again) {
+                reply = MALLOC(maxlen);
+                if (!reply)
+                        return 1;
+
+                c = reply;
+                c += snprint_devices(c, maxlen, vecs);
+                again = ((c - reply) == maxlen);
+                if (again) {
+                        maxlen  *= 2;
+                        FREE(reply);
+                        continue;
+                }
+        }
+
+        *r = reply;
+        *len = (int)(c - reply + 1);
+
+        return 0;
+}
+
+int
+cli_list_devices (void * v, char ** reply, int * len, void * data)
+{
+       struct vectors * vecs = (struct vectors *)data;
+
+        condlog(3, "list devices (operator)");
+
+        return show_devices(reply, len, vecs);
+}
index 8768724..863694b 100644 (file)
@@ -5,6 +5,8 @@ int cli_list_maps_stats (void * v, char ** reply, int * len, void * data);
 int cli_list_map_topology (void * v, char ** reply, int * len, void * data);
 int cli_list_maps_topology (void * v, char ** reply, int * len, void * data);
 int cli_list_config (void * v, char ** reply, int * len, void * data);
+int cli_list_blacklist (void * v, char ** reply, int * len, void * data);
+int cli_list_devices (void * v, char ** reply, int * len, void * data);
 int cli_add_path (void * v, char ** reply, int * len, void * data);
 int cli_del_path (void * v, char ** reply, int * len, void * data);
 int cli_add_map (void * v, char ** reply, int * len, void * data);
index 0b70714..4bb9f0c 100644 (file)
@@ -667,7 +667,7 @@ uev_trigger (struct uevent * uev, void * trigger_data)
        /*
         * path add/remove event
         */
-       if (blacklist(conf->blist_devnode, devname))
+       if (blacklist(conf->blist_devnode, conf->elist_devnode, devname))
                goto out;
 
        if (!strncmp(uev->action, "add", 3)) {
@@ -710,6 +710,8 @@ uxlsnrloop (void * ap)
        add_handler(LIST+TOPOLOGY, cli_list_maps_topology);
        add_handler(LIST+MAP+TOPOLOGY, cli_list_map_topology);
        add_handler(LIST+CONFIG, cli_list_config);
+       add_handler(LIST+BLACKLIST, cli_list_blacklist);
+       add_handler(LIST+DEVICES, cli_list_devices);
        add_handler(ADD+PATH, cli_add_path);
        add_handler(DEL+PATH, cli_del_path);
        add_handler(ADD+MAP, cli_add_map);
index 596bbf3..480b8ed 100644 (file)
@@ -57,6 +57,12 @@ This map could be obtained from "list maps".
 .B list|show config
 Show the currently used configuration, derived from default values and values specified within the configuration file /etc/multipath.conf.
 .TP
+.B list|show blacklist
+Show the currently used blacklist rules, derived from default values and values specified within the configuration file /etc/multipath.conf.
+.TP
+.B list|show devices
+Show all available block devices by name including the information if they are blacklisted or not.
+.TP
 .B add path $path
 Add a path to the list of monitored paths. $path is as listed in /sys/block (e.g. sda).
 .TP