--- libmultipath/blacklist.c | 50 ++++++++++++++++++++++++++---- libmultipath/blacklist.h | 3 + libmultipath/config.c | 16 +++++++++ libmultipath/config.h | 2 + libmultipath/dict.c | 38 +++++++++++++++++++++-- libmultipath/discovery.c | 5 +-- libmultipath/print.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ libmultipath/print.h | 2 + libmultipath/structs.h | 1 multipath/multipath.conf.5 | 15 +++++++++ 10 files changed, 194 insertions(+), 12 deletions(-) Index: multipath-tools-130222/libmultipath/blacklist.c =================================================================== --- multipath-tools-130222.orig/libmultipath/blacklist.c +++ multipath-tools-130222/libmultipath/blacklist.c @@ -12,6 +12,8 @@ #include "structs.h" #include "config.h" #include "blacklist.h" +#include "structs_vec.h" +#include "print.h" extern int store_ble (vector blist, char * str, int origin) @@ -211,12 +213,14 @@ setup_default_blist (struct config * con condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ else if (env) \ condlog(3, "%s: (%s) %s", dev, env, (M)); \ + else if (protocol) \ + condlog(3, "%s: (%s) %s", dev, protocol, (M)); \ else \ condlog(3, "%s: %s", dev, (M)) void log_filter (const char *dev, char *vendor, char *product, char *wwid, - const char *env, int r) + const char *env, char *protocol, int r) { /* * Try to sort from most likely to least. @@ -236,6 +240,9 @@ log_filter (const char *dev, char *vendo case MATCH_PROPERTY_BLIST: LOG_BLIST("udev property blacklisted"); break; + case MATCH_PROTOCOL_BLIST: + LOG_BLIST("protocol blacklisted"); + break; case MATCH_DEVICE_BLIST_EXCEPT: LOG_BLIST("vendor/product whitelisted"); break; @@ -251,6 +258,9 @@ log_filter (const char *dev, char *vendo case MATCH_PROPERTY_BLIST_MISSING: LOG_BLIST("blacklisted, udev property missing"); break; + case MATCH_PROTOCOL_BLIST_EXCEPT: + LOG_BLIST("protocol whitelisted"); + break; } } @@ -270,7 +280,7 @@ int filter_device (vector blist, vector elist, char * vendor, char * product) { int r = _filter_device(blist, elist, vendor, product); - log_filter(NULL, vendor, product, NULL, NULL, r); + log_filter(NULL, vendor, product, NULL, NULL, NULL, r); return r; } @@ -290,7 +300,7 @@ int filter_devnode (vector blist, vector elist, char * dev) { int r = _filter_devnode(blist, elist, dev); - log_filter(dev, NULL, NULL, NULL, NULL, r); + log_filter(dev, NULL, NULL, NULL, NULL, NULL, r); return r; } @@ -310,7 +320,7 @@ int filter_wwid (vector blist, vector elist, char * wwid) { int r = _filter_wwid(blist, elist, wwid); - log_filter(NULL, NULL, NULL, wwid, NULL, r); + log_filter(NULL, NULL, NULL, wwid, NULL, NULL, r); return r; } @@ -346,7 +356,7 @@ filter_property(struct config * conf, st r = _filter_property(conf, env); if (r) { - log_filter(devname, NULL, NULL, NULL, env, r); + log_filter(devname, NULL, NULL, NULL, env, NULL, r); return r; } } @@ -356,13 +366,35 @@ filter_property(struct config * conf, st * the environment variable _has_ to match. */ if (VECTOR_SIZE(conf->elist_property)) { - log_filter(devname, NULL, NULL, NULL, NULL, + log_filter(devname, NULL, NULL, NULL, NULL, NULL, MATCH_PROPERTY_BLIST_MISSING); return MATCH_PROPERTY_BLIST_MISSING; } return 0; } +static int +_filter_protocol(vector blist, vector elist, char *protocol_str) +{ + if (_blacklist_exceptions(elist, protocol_str)) + return MATCH_PROTOCOL_BLIST_EXCEPT; + if (_blacklist(blist, protocol_str)) + return MATCH_PROTOCOL_BLIST; + return 0; +} + +int +filter_protocol(vector blist, vector elist, struct path * pp) +{ + char buf[PROTOCOL_BUF_SIZE]; + int r; + + snprint_path_protocol(buf, sizeof(buf), pp); + r = _filter_protocol(blist, elist, buf); + log_filter(pp->dev, NULL, NULL, NULL, NULL, buf, r); + return r; +} + int _filter_path (struct config * conf, struct path * pp) { @@ -371,6 +403,9 @@ _filter_path (struct config * conf, stru r = filter_property(conf, pp->udev); if (r > 0) return r; + r = filter_protocol(conf->blist_protocol, conf->elist_protocol, pp); + if (r > 0) + return r; r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev); if (r > 0) return r; @@ -386,7 +421,8 @@ int filter_path (struct config * conf, struct path * pp) { int r=_filter_path(conf, pp); - log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, r); + log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, + NULL, r); return r; } Index: multipath-tools-130222/libmultipath/blacklist.h =================================================================== --- multipath-tools-130222.orig/libmultipath/blacklist.h +++ multipath-tools-130222/libmultipath/blacklist.h @@ -10,10 +10,12 @@ #define MATCH_DEVNODE_BLIST 3 #define MATCH_PROPERTY_BLIST 4 #define MATCH_PROPERTY_BLIST_MISSING 5 +#define MATCH_PROTOCOL_BLIST 6 #define MATCH_WWID_BLIST_EXCEPT -MATCH_WWID_BLIST #define MATCH_DEVICE_BLIST_EXCEPT -MATCH_DEVICE_BLIST #define MATCH_DEVNODE_BLIST_EXCEPT -MATCH_DEVNODE_BLIST #define MATCH_PROPERTY_BLIST_EXCEPT -MATCH_PROPERTY_BLIST +#define MATCH_PROTOCOL_BLIST_EXCEPT -MATCH_PROTOCOL_BLIST struct blentry { char * str; @@ -36,6 +38,7 @@ int filter_wwid (vector, vector, char *) int filter_device (vector, vector, char *, char *); int filter_path (struct config *, struct path *); int filter_property(struct config *, struct udev_device *); +int filter_protocol(vector, vector, struct path *); int store_ble (vector, char *, int); int set_ble_device (vector, char *, char *, int); void free_blacklist (vector); Index: multipath-tools-130222/libmultipath/config.c =================================================================== --- multipath-tools-130222.orig/libmultipath/config.c +++ multipath-tools-130222/libmultipath/config.c @@ -600,11 +600,13 @@ free_config (struct config * conf) free_blacklist(conf->blist_devnode); free_blacklist(conf->blist_wwid); free_blacklist(conf->blist_property); + free_blacklist(conf->blist_protocol); free_blacklist_device(conf->blist_device); free_blacklist(conf->elist_devnode); free_blacklist(conf->elist_wwid); free_blacklist(conf->elist_property); + free_blacklist(conf->elist_protocol); free_blacklist_device(conf->elist_device); free_mptable(conf->mptable); @@ -792,6 +794,13 @@ load_config (char * file, struct udev *u goto out; } + if (conf->blist_protocol == NULL) { + conf->blist_protocol = vector_alloc(); + + if (!conf->blist_protocol) + goto out; + } + if (conf->elist_devnode == NULL) { conf->elist_devnode = vector_alloc(); @@ -819,6 +828,13 @@ load_config (char * file, struct udev *u goto out; } + if (conf->elist_protocol == NULL) { + conf->elist_protocol = vector_alloc(); + + if (!conf->elist_protocol) + goto out; + } + if (setup_default_blist(conf)) goto out; Index: multipath-tools-130222/libmultipath/config.h =================================================================== --- multipath-tools-130222.orig/libmultipath/config.h +++ multipath-tools-130222/libmultipath/config.h @@ -194,10 +194,12 @@ struct config { vector blist_wwid; vector blist_device; vector blist_property; + vector blist_protocol; vector elist_devnode; vector elist_wwid; vector elist_device; vector elist_property; + vector elist_protocol; }; struct config * conf; Index: multipath-tools-130222/libmultipath/dict.c =================================================================== --- multipath-tools-130222.orig/libmultipath/dict.c +++ multipath-tools-130222/libmultipath/dict.c @@ -1092,9 +1092,12 @@ blacklist_handler(vector strvec) conf->blist_device = vector_alloc(); if (!conf->blist_property) conf->blist_property = vector_alloc(); + if (!conf->blist_protocol) + conf->blist_protocol = vector_alloc(); if (!conf->blist_devnode || !conf->blist_wwid || - !conf->blist_device || !conf->blist_property) + !conf->blist_device || !conf->blist_property || + !conf->blist_protocol) return 1; return 0; @@ -1111,9 +1114,12 @@ blacklist_exceptions_handler(vector strv conf->elist_device = vector_alloc(); if (!conf->elist_property) conf->elist_property = vector_alloc(); + if (!conf->elist_protocol) + conf->elist_protocol = vector_alloc(); if (!conf->elist_devnode || !conf->elist_wwid || - !conf->elist_device || !conf->elist_property) + !conf->elist_device || !conf->elist_property || + !conf->elist_protocol) return 1; return 0; @@ -1198,6 +1204,32 @@ ble_except_property_handler(vector strve } static int +ble_protocol_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + + if (!buff) + return 1; + + return store_ble(conf->blist_protocol, buff, ORIGIN_CONFIG); +} + +static int +ble_except_protocol_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + + if (!buff) + return 1; + + return store_ble(conf->elist_protocol, buff, ORIGIN_CONFIG); +} + +static int ble_device_handler(vector strvec) { return alloc_ble_device(conf->blist_device); @@ -4021,6 +4053,7 @@ init_keywords(void) install_keyword_multi("devnode", &ble_devnode_handler, &snprint_ble_simple); install_keyword_multi("wwid", &ble_wwid_handler, &snprint_ble_simple); install_keyword_multi("property", &ble_property_handler, &snprint_ble_simple); + install_keyword_multi("protocol", &ble_protocol_handler, &snprint_ble_simple); install_keyword_multi("device", &ble_device_handler, NULL); install_sublevel(); install_keyword("vendor", &ble_vendor_handler, &snprint_bled_vendor); @@ -4030,6 +4063,7 @@ init_keywords(void) install_keyword_multi("devnode", &ble_except_devnode_handler, &snprint_ble_simple); install_keyword_multi("wwid", &ble_except_wwid_handler, &snprint_ble_simple); install_keyword_multi("property", &ble_except_property_handler, &snprint_ble_simple); + install_keyword_multi("protocol", &ble_except_protocol_handler, &snprint_ble_simple); install_keyword_multi("device", &ble_except_device_handler, NULL); install_sublevel(); install_keyword("vendor", &ble_except_vendor_handler, &snprint_bled_vendor); Index: multipath-tools-130222/libmultipath/print.c =================================================================== --- multipath-tools-130222.orig/libmultipath/print.c +++ multipath-tools-130222/libmultipath/print.c @@ -607,6 +607,48 @@ snprint_path_failures(char * buff, size_ return snprint_int(buff, len, pp->failcount); } +/* if you add a protocol string bigger than "scsi:unspec" you must + * also change PROTOCOL_BUF_SIZE */ +int +snprint_path_protocol(char * buff, size_t len, struct path * pp) +{ + switch (pp->bus) { + case SYSFS_BUS_SCSI: + switch (pp->sg_id.proto_id) { + case SCSI_PROTOCOL_FCP: + return snprintf(buff, len, "scsi:fcp"); + case SCSI_PROTOCOL_SPI: + return snprintf(buff, len, "scsi:spi"); + case SCSI_PROTOCOL_SSA: + return snprintf(buff, len, "scsi:ssa"); + case SCSI_PROTOCOL_SBP: + return snprintf(buff, len, "scsi:sbp"); + case SCSI_PROTOCOL_SRP: + return snprintf(buff, len, "scsi:srp"); + case SCSI_PROTOCOL_ISCSI: + return snprintf(buff, len, "scsi:iscsi"); + case SCSI_PROTOCOL_SAS: + return snprintf(buff, len, "scsi:sas"); + case SCSI_PROTOCOL_ADT: + return snprintf(buff, len, "scsi:adt"); + case SCSI_PROTOCOL_ATA: + return snprintf(buff, len, "scsi:ata"); + case SCSI_PROTOCOL_UNSPEC: + default: + return snprintf(buff, len, "scsi:unspec"); + } + case SYSFS_BUS_CCW: + return snprintf(buff, len, "ccw"); + case SYSFS_BUS_CCISS: + return snprintf(buff, len, "cciss"); + case SYSFS_BUS_NVME: + return snprintf(buff, len, "nvme"); + case SYSFS_BUS_UNDEF: + default: + return snprintf(buff, len, "undef"); + } +} + struct multipath_data mpd[] = { {'n', "name", 0, snprint_name}, {'w', "uuid", 0, snprint_multipath_uuid}, @@ -654,6 +696,7 @@ struct path_data pd[] = { {'r', "target WWPN", 0, snprint_tgt_wwpn}, {'a', "host adapter", 0, snprint_host_adapter}, {'0', "failures", 0, snprint_path_failures}, + {'P', "protocol", 0, snprint_path_protocol}, {0, NULL, 0 , NULL} }; @@ -1435,6 +1478,19 @@ snprint_blacklist_report (char * buff, i if ((len - fwd - threshold) <= 0) return len; + fwd += snprintf(buff + fwd, len - fwd, "protocol rules:\n" + "- blacklist:\n"); + if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_protocol)) + 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_protocol) == 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) @@ -1509,6 +1565,15 @@ snprint_blacklist (char * buff, int len) if (fwd > len) return len; } + vector_foreach_slot (conf->blist_protocol, ble, i) { + kw = find_keyword(rootkw->sub, "protocol"); + if (!kw) + return 0; + fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", + kw, ble); + if (fwd > len) + return len; + } rootkw = find_keyword(rootkw->sub, "device"); if (!rootkw) return 0; @@ -1582,6 +1647,15 @@ snprint_blacklist_except (char * buff, i 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_protocol, ele, i) { + kw = find_keyword(rootkw->sub, "protocol"); + if (!kw) + return 0; + fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", kw, ele); if (fwd > len) return len; Index: multipath-tools-130222/libmultipath/print.h =================================================================== --- multipath-tools-130222.orig/libmultipath/print.h +++ multipath-tools-130222/libmultipath/print.h @@ -115,6 +115,8 @@ int snprint_host_wwnn (char *, size_t, s int snprint_host_wwpn (char *, size_t, struct path *); int snprint_tgt_wwnn (char *, size_t, struct path *); int snprint_tgt_wwpn (char *, size_t, struct path *); +#define PROTOCOL_BUF_SIZE sizeof("scsi:unspec") +int snprint_path_protocol(char *, size_t, struct path *); void print_multipath_topology (struct multipath * mpp, int verbosity); void print_path (struct path * pp, char * style); Index: multipath-tools-130222/libmultipath/structs.h =================================================================== --- multipath-tools-130222.orig/libmultipath/structs.h +++ multipath-tools-130222/libmultipath/structs.h @@ -57,7 +57,6 @@ enum failback_mode { enum sysfs_buses { SYSFS_BUS_UNDEF, SYSFS_BUS_SCSI, - SYSFS_BUS_IDE, SYSFS_BUS_CCW, SYSFS_BUS_CCISS, SYSFS_BUS_NVME, Index: multipath-tools-130222/libmultipath/discovery.c =================================================================== --- multipath-tools-130222.orig/libmultipath/discovery.c +++ multipath-tools-130222/libmultipath/discovery.c @@ -1407,9 +1407,10 @@ pathinfo (struct path *pp, vector hwtabl if (mask & DI_BLACKLIST && mask & DI_SYSFS) { if (filter_device(conf->blist_device, conf->elist_device, - pp->vendor_id, pp->product_id) > 0) { + pp->vendor_id, pp->product_id) > 0 || + filter_protocol(conf->blist_protocol, conf->elist_protocol, + pp) > 0) return PATHINFO_SKIPPED; - } } path_state = path_offline(pp); Index: multipath-tools-130222/multipath/multipath.conf.5 =================================================================== --- multipath-tools-130222.orig/multipath/multipath.conf.5 +++ multipath-tools-130222/multipath/multipath.conf.5 @@ -640,6 +640,10 @@ Regular expression of the device nodes t .B property Regular expresion of the udev property to be excluded. .TP +.B protocol +Regular expression of the protocol to be excluded. See below for a +list of recognized protocols +.TP .B device Subsection for the device description. This subsection recognizes the .I vendor @@ -648,6 +652,13 @@ and keywords. For a full description of these keywords please see the .I devices section description. +.LP +The protocol strings that multipath recognizes are \fIscsi:fcp\fR, +\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR, +\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR, +\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. +The protocol that a path is using can be viewed by running +\fBmultipathd show paths format "%d %P"\fR .SH "blacklist_exceptions section" The .I blacklist_exceptions @@ -667,6 +678,10 @@ The \fIWorld Wide Identification\fR of a .B property Regular expresion of the udev property to be whitelisted. .TP +.B protocol +Regular expression of the protocol to be whitelisted. See the +\fBblacklist section\fR for a list of recognized protocols +.TP .B devnode Regular expression of the device nodes to be whitelisted. .TP