diff --git a/SOURCES/0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch b/SOURCES/0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch new file mode 100644 index 0000000..9862e22 --- /dev/null +++ b/SOURCES/0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 3 Nov 2020 14:27:58 -0600 +Subject: [PATCH] libmultipath: factor out code to get vpd page data + +A future patch will reuse the code to get the vpd page data, so factor +it out from get_vpd_sgio(). + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index aa5942c3..eb1e735d 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1239,11 +1239,10 @@ get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen) + return len; + } + +-int +-get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen) ++static int ++fetch_vpd_page(int fd, int pg, unsigned char *buff) + { +- int len, buff_len; +- unsigned char buff[4096]; ++ int buff_len; + + memset(buff, 0x0, 4096); + if (sgio_get_vpd(buff, 4096, fd, pg) < 0) { +@@ -1264,6 +1263,18 @@ get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen) + condlog(3, "vpd pg%02x page truncated", pg); + buff_len = 4096; + } ++ return buff_len; ++} ++ ++int ++get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen) ++{ ++ int len, buff_len; ++ unsigned char buff[4096]; ++ ++ buff_len = fetch_vpd_page(fd, pg, buff); ++ if (buff_len < 0) ++ return buff_len; + if (pg == 0x80) + len = parse_vpd_pg80(buff, str, maxlen); + else if (pg == 0x83) +-- +2.17.2 + diff --git a/SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch b/SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch new file mode 100644 index 0000000..d23bdaf --- /dev/null +++ b/SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 7 Oct 2020 21:43:02 -0500 +Subject: [PATCH] libmultipath: limit reading 0xc9 vpd page + +Only rdac arrays support 0xC9 vpd page inquiries. All other arrays will +return a failure. Only do the rdac inquiry when detecting array +capabilities if the array's path checker is explicitly set to rdac, or +the path checker is not set, and the array reports that it supports vpd +page 0xC9 in the Supported VPD Pages (0x00) vpd page. + +Multipath was doing the check if either the path checker was set to +rdac, or no path checker was set. This means that for almost all +non-rdac arrays, multipath was issuing a bad inquiry. This was annoying +users. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 25 +++++++++++++++++++++++++ + libmultipath/discovery.h | 1 + + libmultipath/propsel.c | 10 ++++++---- + 3 files changed, 32 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index eb1e735d..01aadba9 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1266,6 +1266,31 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff) + return buff_len; + } + ++/* heavily based on sg_inq.c from sg3_utils */ ++bool ++is_vpd_page_supported(int fd, int pg) ++{ ++ int i, len, buff_len; ++ unsigned char buff[4096]; ++ ++ buff_len = fetch_vpd_page(fd, 0x00, buff); ++ if (buff_len < 0) ++ return false; ++ if (buff_len < 4) { ++ condlog(3, "VPD page 00h too short"); ++ return false; ++ } ++ ++ len = buff[3] + 4; ++ if (len > buff_len) ++ condlog(3, "vpd page 00h trucated, expected %d, have %d", ++ len, buff_len); ++ for (i = 4; i < len; ++i) ++ if (buff[i] == pg) ++ return true; ++ return false; ++} ++ + int + get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen) + { +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index 6444887d..d3193daf 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -56,6 +56,7 @@ int sysfs_get_asymmetric_access_state(struct path *pp, + char *buff, int buflen); + int get_uid(struct path * pp, int path_state, struct udev_device *udev, + int allow_fallback); ++bool is_vpd_page_supported(int fd, int pg); + + /* + * discovery bitmask +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index d362beb4..d7febec6 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -496,13 +496,15 @@ check_rdac(struct path * pp) + { + int len; + char buff[44]; +- const char *checker_name; ++ const char *checker_name = NULL; + + if (pp->bus != SYSFS_BUS_SCSI) + return 0; +- /* Avoid ioctl if this is likely not an RDAC array */ +- if (__do_set_from_hwe(checker_name, pp, checker_name) && +- strcmp(checker_name, RDAC)) ++ /* Avoid checking 0xc9 if this is likely not an RDAC array */ ++ if (!__do_set_from_hwe(checker_name, pp, checker_name) && ++ !is_vpd_page_supported(pp->fd, 0xC9)) ++ return 0; ++ if (checker_name && strcmp(checker_name, RDAC)) + return 0; + len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44); + if (len <= 0) +-- +2.17.2 + diff --git a/SOURCES/0041-libmultipath-add-device-to-hwtable.c.patch b/SOURCES/0041-libmultipath-add-device-to-hwtable.c.patch new file mode 100644 index 0000000..9d5e780 --- /dev/null +++ b/SOURCES/0041-libmultipath-add-device-to-hwtable.c.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Steve Schremmer +Date: Mon, 6 Jul 2020 20:22:35 +0000 +Subject: [PATCH] libmultipath: add device to hwtable.c + +Add FUJITSU ETERNUS_AHB defaults. + +Signed-off-by: Steve Schremmer +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/hwtable.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index d1fcfdb3..d680bdfc 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -428,6 +428,22 @@ static struct hwentry default_hw[] = { + .pgpolicy = MULTIBUS, + .no_path_retry = 10, + }, ++ { ++ /* ++ * ETERNUS AB/HB ++ * Maintainer: NetApp RDAC team ++ */ ++ .vendor = "FUJITSU", ++ .product = "ETERNUS_AHB", ++ .bl_product = "Universal Xport", ++ .pgpolicy = GROUP_BY_PRIO, ++ .checker_name = RDAC, ++ .features = "2 pg_init_retries 50", ++ .hwhandler = "1 rdac", ++ .prio_name = PRIO_RDAC, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .no_path_retry = 30, ++ }, + /* + * Hitachi Vantara + * +-- +2.17.2 + diff --git a/SOURCES/0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch b/SOURCES/0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch new file mode 100644 index 0000000..0cd6997 --- /dev/null +++ b/SOURCES/0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch @@ -0,0 +1,159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 12 Oct 2020 16:06:11 -0500 +Subject: [PATCH] libmultipath: move fast_io_fail defines to structs.h + +Since fast_io_fail is part of the multipath struct, its symbolic values +belong in structs.h. Also, make it an instance of a general enum, which +will be used again in future patches, and change the set/print functions +which use it to use the general enum instead. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.h | 8 -------- + libmultipath/dict.c | 30 +++++++++++++++--------------- + libmultipath/dict.h | 2 +- + libmultipath/propsel.c | 2 +- + libmultipath/structs.h | 17 +++++++++++++++++ + 5 files changed, 34 insertions(+), 25 deletions(-) + +diff --git a/libmultipath/config.h b/libmultipath/config.h +index 160867cd..f38c7639 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -11,14 +11,6 @@ + #define ORIGIN_CONFIG 1 + #define ORIGIN_NO_CONFIG 2 + +-/* +- * In kernel, fast_io_fail == 0 means immediate failure on rport delete. +- * OTOH '0' means not-configured in various places in multipath-tools. +- */ +-#define MP_FAST_IO_FAIL_UNSET (0) +-#define MP_FAST_IO_FAIL_OFF (-1) +-#define MP_FAST_IO_FAIL_ZERO (-2) +- + enum devtypes { + DEV_NONE, + DEV_DEVT, +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 184d4b22..ce8e1cda 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -834,7 +834,7 @@ declare_mp_attr_handler(gid, set_gid) + declare_mp_attr_snprint(gid, print_gid) + + static int +-set_fast_io_fail(vector strvec, void *ptr) ++set_undef_off_zero(vector strvec, void *ptr) + { + char * buff; + int *int_ptr = (int *)ptr; +@@ -844,36 +844,36 @@ set_fast_io_fail(vector strvec, void *ptr) + return 1; + + if (strcmp(buff, "off") == 0) +- *int_ptr = MP_FAST_IO_FAIL_OFF; ++ *int_ptr = UOZ_OFF; + else if (sscanf(buff, "%d", int_ptr) != 1 || +- *int_ptr < MP_FAST_IO_FAIL_ZERO) +- *int_ptr = MP_FAST_IO_FAIL_UNSET; ++ *int_ptr < UOZ_ZERO) ++ *int_ptr = UOZ_UNDEF; + else if (*int_ptr == 0) +- *int_ptr = MP_FAST_IO_FAIL_ZERO; ++ *int_ptr = UOZ_ZERO; + + FREE(buff); + return 0; + } + + int +-print_fast_io_fail(char * buff, int len, long v) ++print_undef_off_zero(char * buff, int len, long v) + { +- if (v == MP_FAST_IO_FAIL_UNSET) ++ if (v == UOZ_UNDEF) + return 0; +- if (v == MP_FAST_IO_FAIL_OFF) ++ if (v == UOZ_OFF) + return snprintf(buff, len, "\"off\""); +- if (v == MP_FAST_IO_FAIL_ZERO) ++ if (v == UOZ_ZERO) + return snprintf(buff, len, "0"); + return snprintf(buff, len, "%ld", v); + } + +-declare_def_handler(fast_io_fail, set_fast_io_fail) +-declare_def_snprint_defint(fast_io_fail, print_fast_io_fail, ++declare_def_handler(fast_io_fail, set_undef_off_zero) ++declare_def_snprint_defint(fast_io_fail, print_undef_off_zero, + DEFAULT_FAST_IO_FAIL) +-declare_ovr_handler(fast_io_fail, set_fast_io_fail) +-declare_ovr_snprint(fast_io_fail, print_fast_io_fail) +-declare_hw_handler(fast_io_fail, set_fast_io_fail) +-declare_hw_snprint(fast_io_fail, print_fast_io_fail) ++declare_ovr_handler(fast_io_fail, set_undef_off_zero) ++declare_ovr_snprint(fast_io_fail, print_undef_off_zero) ++declare_hw_handler(fast_io_fail, set_undef_off_zero) ++declare_hw_snprint(fast_io_fail, print_undef_off_zero) + + static int + set_dev_loss(vector strvec, void *ptr) +diff --git a/libmultipath/dict.h b/libmultipath/dict.h +index a40ac66f..a917e1ca 100644 +--- a/libmultipath/dict.h ++++ b/libmultipath/dict.h +@@ -13,7 +13,7 @@ int print_rr_weight(char *buff, int len, long v); + int print_pgfailback(char *buff, int len, long v); + int print_pgpolicy(char *buff, int len, long v); + int print_no_path_retry(char *buff, int len, long v); +-int print_fast_io_fail(char *buff, int len, long v); ++int print_undef_off_zero(char *buff, int len, long v); + int print_dev_loss(char *buff, int len, unsigned long v); + int print_reservation_key(char * buff, int len, struct be64 key, uint8_t + flags, int source); +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index d7febec6..725db2b1 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -755,7 +755,7 @@ int select_fast_io_fail(struct config *conf, struct multipath *mp) + mp_set_conf(fast_io_fail); + mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL); + out: +- print_fast_io_fail(buff, 12, mp->fast_io_fail); ++ print_undef_off_zero(buff, 12, mp->fast_io_fail); + condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias, buff, origin); + return 0; + } +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 8e78b8c0..29209984 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -229,6 +229,23 @@ enum vpd_vendor_ids { + VPD_VP_ARRAY_SIZE, /* This must remain the last entry */ + }; + ++/* ++ * Multipath treats 0 as undefined for optional config parameters. ++ * Use this for cases where 0 is a valid option for systems multipath ++ * is communicating with ++ */ ++enum undefined_off_zero { ++ UOZ_UNDEF = 0, ++ UOZ_OFF = -1, ++ UOZ_ZERO = -2, ++}; ++ ++enum fast_io_fail_states { ++ MP_FAST_IO_FAIL_UNSET = UOZ_UNDEF, ++ MP_FAST_IO_FAIL_OFF = UOZ_OFF, ++ MP_FAST_IO_FAIL_ZERO = UOZ_ZERO, ++}; ++ + struct vpd_vendor_page { + int pg; + const char *name; +-- +2.17.2 + diff --git a/SOURCES/0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch b/SOURCES/0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch new file mode 100644 index 0000000..a8ebb2c --- /dev/null +++ b/SOURCES/0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch @@ -0,0 +1,295 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 14 Oct 2020 18:38:20 -0500 +Subject: [PATCH] libmultipath: add eh_deadline multipath.conf parameter + +There are times a fc rport is never lost, meaning that fast_io_fail_tmo +and dev_loss_tmo never trigger, but scsi commands still hang. This can +cause problems in cases where users have string timing requirements, and +the easiest way to solve these issues is to set eh_deadline. Since it's +already possible to set fast_io_fail_tmo and dev_loss_tmo from +multipath.conf, and have multipath take care of setting it correctly for +the scsi devices in sysfs, it makes sense to allow users to set +eh_deadline here as well. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 2 ++ + libmultipath/config.h | 2 ++ + libmultipath/configure.c | 1 + + libmultipath/dict.c | 10 +++++++ + libmultipath/discovery.c | 58 +++++++++++++++++++++++++++++++++----- + libmultipath/propsel.c | 17 +++++++++++ + libmultipath/propsel.h | 1 + + libmultipath/structs.h | 7 +++++ + multipath/multipath.conf.5 | 16 +++++++++++ + 9 files changed, 107 insertions(+), 7 deletions(-) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 26f8e050..a71db2d0 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -359,6 +359,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src) + merge_num(flush_on_last_del); + merge_num(fast_io_fail); + merge_num(dev_loss); ++ merge_num(eh_deadline); + merge_num(user_friendly_names); + merge_num(retain_hwhandler); + merge_num(detect_prio); +@@ -514,6 +515,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe) + hwe->flush_on_last_del = dhwe->flush_on_last_del; + hwe->fast_io_fail = dhwe->fast_io_fail; + hwe->dev_loss = dhwe->dev_loss; ++ hwe->eh_deadline = dhwe->eh_deadline; + hwe->user_friendly_names = dhwe->user_friendly_names; + hwe->retain_hwhandler = dhwe->retain_hwhandler; + hwe->detect_prio = dhwe->detect_prio; +diff --git a/libmultipath/config.h b/libmultipath/config.h +index f38c7639..a22c1b4e 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -64,6 +64,7 @@ struct hwentry { + int flush_on_last_del; + int fast_io_fail; + unsigned int dev_loss; ++ int eh_deadline; + int user_friendly_names; + int retain_hwhandler; + int detect_prio; +@@ -149,6 +150,7 @@ struct config { + int attribute_flags; + int fast_io_fail; + unsigned int dev_loss; ++ int eh_deadline; + int log_checker_err; + int allow_queueing; + int find_multipaths; +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 96c79610..b7113291 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -340,6 +340,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size, + select_gid(conf, mpp); + select_fast_io_fail(conf, mpp); + select_dev_loss(conf, mpp); ++ select_eh_deadline(conf, mpp); + select_reservation_key(conf, mpp); + select_deferred_remove(conf, mpp); + select_marginal_path_err_sample_time(conf, mpp); +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index ce8e1cda..8fd91d8c 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -911,6 +911,13 @@ declare_ovr_snprint(dev_loss, print_dev_loss) + declare_hw_handler(dev_loss, set_dev_loss) + declare_hw_snprint(dev_loss, print_dev_loss) + ++declare_def_handler(eh_deadline, set_undef_off_zero) ++declare_def_snprint(eh_deadline, print_undef_off_zero) ++declare_ovr_handler(eh_deadline, set_undef_off_zero) ++declare_ovr_snprint(eh_deadline, print_undef_off_zero) ++declare_hw_handler(eh_deadline, set_undef_off_zero) ++declare_hw_snprint(eh_deadline, print_undef_off_zero) ++ + static int + set_pgpolicy(vector strvec, void *ptr) + { +@@ -1776,6 +1783,7 @@ init_keywords(vector keywords) + install_keyword("gid", &def_gid_handler, &snprint_def_gid); + install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail); + install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); ++ install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline); + install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file); + install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file); + install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file); +@@ -1885,6 +1893,7 @@ init_keywords(vector keywords) + install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del); + install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail); + install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss); ++ install_keyword("eh_deadline", &hw_eh_deadline_handler, &snprint_hw_eh_deadline); + install_keyword("user_friendly_names", &hw_user_friendly_names_handler, &snprint_hw_user_friendly_names); + install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler); + install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio); +@@ -1925,6 +1934,7 @@ init_keywords(vector keywords) + install_keyword("flush_on_last_del", &ovr_flush_on_last_del_handler, &snprint_ovr_flush_on_last_del); + install_keyword("fast_io_fail_tmo", &ovr_fast_io_fail_handler, &snprint_ovr_fast_io_fail); + install_keyword("dev_loss_tmo", &ovr_dev_loss_handler, &snprint_ovr_dev_loss); ++ install_keyword("eh_deadline", &ovr_eh_deadline_handler, &snprint_ovr_eh_deadline); + install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names); + install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler); + install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 01aadba9..a328aafa 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -577,6 +577,42 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen) + return !!preferred; + } + ++static int ++sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp) ++{ ++ struct udev_device *hostdev; ++ char host_name[HOST_NAME_LEN], value[16]; ++ int ret; ++ ++ if (mpp->eh_deadline == EH_DEADLINE_UNSET) ++ return 0; ++ ++ sprintf(host_name, "host%d", pp->sg_id.host_no); ++ hostdev = udev_device_new_from_subsystem_sysname(udev, ++ "scsi_host", host_name); ++ if (!hostdev) ++ return 1; ++ ++ if (mpp->eh_deadline == EH_DEADLINE_OFF) ++ sprintf(value, "off"); ++ else if (mpp->eh_deadline == EH_DEADLINE_ZERO) ++ sprintf(value, "0"); ++ else ++ snprintf(value, 16, "%u", mpp->eh_deadline); ++ ++ ret = sysfs_attr_set_value(hostdev, "eh_deadline", ++ value, strlen(value)); ++ /* ++ * not all scsi drivers support setting eh_deadline, so failing ++ * is totally reasonable ++ */ ++ if (ret <= 0) ++ condlog(4, "%s: failed to set eh_deadline to %s, error %d", udev_device_get_sysname(hostdev), value, -ret); ++ ++ udev_device_unref(hostdev); ++ return (ret <= 0); ++} ++ + static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { +@@ -787,16 +823,24 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint) + mpp->alias, mpp->fast_io_fail); + mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF; + } +- if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) ++ if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET && ++ mpp->eh_deadline == EH_DEADLINE_UNSET) + return 0; + + vector_foreach_slot(mpp->paths, pp, i) { +- if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) +- sysfs_set_rport_tmo(mpp, pp); +- if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI) +- sysfs_set_session_tmo(mpp, pp); +- if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS) +- sysfs_set_nexus_loss_tmo(mpp, pp); ++ if (pp->bus != SYSFS_BUS_SCSI) ++ continue; ++ ++ if (mpp->dev_loss || ++ mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { ++ if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) ++ sysfs_set_rport_tmo(mpp, pp); ++ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI) ++ sysfs_set_session_tmo(mpp, pp); ++ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS) ++ sysfs_set_nexus_loss_tmo(mpp, pp); ++ } ++ sysfs_set_eh_deadline(mpp, pp); + } + return 0; + } +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index 725db2b1..1150cfe8 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -776,6 +776,23 @@ out: + return 0; + } + ++int select_eh_deadline(struct config *conf, struct multipath *mp) ++{ ++ const char *origin; ++ char buff[12]; ++ ++ mp_set_ovr(eh_deadline); ++ mp_set_hwe(eh_deadline); ++ mp_set_conf(eh_deadline); ++ mp->eh_deadline = EH_DEADLINE_UNSET; ++ /* not changing sysfs in default cause, so don't print anything */ ++ return 0; ++out: ++ print_undef_off_zero(buff, 12, mp->eh_deadline); ++ condlog(3, "%s: eh_deadline = %s %s", mp->alias, buff, origin); ++ return 0; ++} ++ + int select_flush_on_last_del(struct config *conf, struct multipath *mp) + { + const char *origin; +diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h +index 3d6edd8a..a68bacf0 100644 +--- a/libmultipath/propsel.h ++++ b/libmultipath/propsel.h +@@ -17,6 +17,7 @@ int select_uid(struct config *conf, struct multipath *mp); + int select_gid(struct config *conf, struct multipath *mp); + int select_fast_io_fail(struct config *conf, struct multipath *mp); + int select_dev_loss(struct config *conf, struct multipath *mp); ++int select_eh_deadline(struct config *conf, struct multipath *mp); + int select_reservation_key(struct config *conf, struct multipath *mp); + int select_retain_hwhandler (struct config *conf, struct multipath * mp); + int select_detect_prio(struct config *conf, struct path * pp); +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 29209984..65542dea 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -246,6 +246,12 @@ enum fast_io_fail_states { + MP_FAST_IO_FAIL_ZERO = UOZ_ZERO, + }; + ++enum eh_deadline_states { ++ EH_DEADLINE_UNSET = UOZ_UNDEF, ++ EH_DEADLINE_OFF = UOZ_OFF, ++ EH_DEADLINE_ZERO = UOZ_ZERO, ++}; ++ + struct vpd_vendor_page { + int pg; + const char *name; +@@ -366,6 +372,7 @@ struct multipath { + int ghost_delay; + int ghost_delay_tick; + unsigned int dev_loss; ++ int eh_deadline; + uid_t uid; + gid_t gid; + mode_t mode; +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 6dc26f10..60954574 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -700,6 +700,22 @@ The default is: \fB600\fR + . + . + .TP ++.B eh_deadline ++Specify the maximum number of seconds the SCSI layer will spend doing error ++handling when scsi devices fail. After this timeout the scsi layer will perform ++a full HBA reset. Setting this may be necessary in cases where the rport is ++never lost, so \fIfast_io_fail_tmo\fR and \fIdev_loss_tmo\fR will never ++trigger, but (frequently do to load) scsi commands still hang. \fBNote:\fR when ++the scsi error handler performs the HBA reset, all target paths on that HBA ++will be affected. eh_deadline should only be set in cases where all targets on ++the affected HBAs are multipathed. ++.RS ++.TP ++The default is: \fB\fR ++.RE ++. ++. ++.TP + .B bindings_file + The full pathname of the binding file to be used when the user_friendly_names + option is set. +-- +2.17.2 + diff --git a/SOURCES/0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch b/SOURCES/0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch new file mode 100644 index 0000000..18ed578 --- /dev/null +++ b/SOURCES/0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 23 Oct 2020 11:38:24 -0500 +Subject: [PATCH] libmultipath: don't dlclose tur checker DSO + +The multipathd tur checker thread is designed to be able to finish at +any time, even after the tur checker itself has been freed. The +multipathd shutdown code makes sure all the checkers have been freed +before freeing the checker_class and calling dlclose() to unload the +DSO, but this doesn't guarantee that the checker threads have finished. +If one hasn't, the DSO will get unloaded while the thread still running +code from it, causing a segfault. Unfortunately, it's not possible to be +sure that all tur checker threads have ended during shutdown, without +making them joinable. + +However, since libmultipath will never be reinitialized after it has +been uninitialzed, not dlclosing the tur checker DSO once a thread is +started has minimal cost (keeping the DSO code around until the program +exits, which usually happens right after freeing the checkers). + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/checkers.c | 10 +++++++++- + libmultipath/checkers.h | 1 + + libmultipath/checkers/tur.c | 1 + + 3 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c +index 8d2be8a9..6359e5d8 100644 +--- a/libmultipath/checkers.c ++++ b/libmultipath/checkers.c +@@ -21,6 +21,7 @@ struct checker_class { + void (*reset)(void); /* to reset the global variables */ + const char **msgtable; + short msgtable_size; ++ int keep_dso; + }; + + char *checker_state_names[] = { +@@ -69,7 +70,7 @@ void free_checker_class(struct checker_class *c) + list_del(&c->node); + if (c->reset) + c->reset(); +- if (c->handle) { ++ if (c->handle && !c->keep_dso) { + if (dlclose(c->handle) != 0) { + condlog(0, "Cannot unload checker %s: %s", + c->name, dlerror()); +@@ -192,6 +193,13 @@ out: + return NULL; + } + ++void checker_keep_dso(struct checker * c) ++{ ++ if (!c || !c->cls) ++ return; ++ c->cls->keep_dso = 1; ++} ++ + void checker_set_fd (struct checker * c, int fd) + { + if (!c) +diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h +index b458118d..f183cff9 100644 +--- a/libmultipath/checkers.h ++++ b/libmultipath/checkers.h +@@ -145,6 +145,7 @@ void checker_reset (struct checker *); + void checker_set_sync (struct checker *); + void checker_set_async (struct checker *); + void checker_set_fd (struct checker *, int); ++void checker_keep_dso(struct checker *c); + void checker_enable (struct checker *); + void checker_disable (struct checker *); + int checker_check (struct checker *, int); +diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c +index e886fcf8..fd58d62a 100644 +--- a/libmultipath/checkers/tur.c ++++ b/libmultipath/checkers/tur.c +@@ -394,6 +394,7 @@ int libcheck_check(struct checker * c) + uatomic_set(&ct->running, 1); + tur_set_async_timeout(c); + setup_thread_attr(&attr, 32 * 1024, 1); ++ checker_keep_dso(c); + r = pthread_create(&ct->thread, &attr, tur_thread, ct); + pthread_attr_destroy(&attr); + if (r) { +-- +2.17.2 + diff --git a/SOURCES/0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch b/SOURCES/0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch new file mode 100644 index 0000000..f8f45f8 --- /dev/null +++ b/SOURCES/0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 16 Nov 2020 13:52:09 -0600 +Subject: [PATCH] libmultipath: warn about missing braces at end of + multipath.conf + +Multipath doesn't warn when multipath.conf is missing closing braces at +the end of the file. This has confused people about the correct config +file syntax, so add a warning. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/parser.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/parser.c b/libmultipath/parser.c +index a7285a35..48b54e87 100644 +--- a/libmultipath/parser.c ++++ b/libmultipath/parser.c +@@ -544,7 +544,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file) + if (!strcmp(str, EOB)) { + if (kw_level > 0) { + free_strvec(strvec); +- break; ++ goto out; + } + condlog(0, "unmatched '%s' at line %d of %s", + EOB, line_nr, file); +@@ -583,7 +583,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file) + + free_strvec(strvec); + } +- ++ if (kw_level == 1) ++ condlog(1, "missing '%s' at end of %s", EOB, file); + out: + FREE(buf); + free_uniques(uniques); +-- +2.17.2 + diff --git a/SOURCES/0046-libmultipath-ignore-multipaths-sections-without-wwid.patch b/SOURCES/0046-libmultipath-ignore-multipaths-sections-without-wwid.patch new file mode 100644 index 0000000..3ccf175 --- /dev/null +++ b/SOURCES/0046-libmultipath-ignore-multipaths-sections-without-wwid.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 16 Nov 2020 16:38:21 -0600 +Subject: [PATCH] libmultipath: ignore multipaths sections without wwid option + +"multipathd show config local" was crashing in find_mp_by_wwid() if +the multipath configuration included a multipaths section that did +not set a wwid option. There is no reason to keep a mpentry that +didn't set its wwid. Remove it in merge_mptable(). + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index a71db2d0..dc81c994 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -444,6 +444,13 @@ void merge_mptable(vector mptable) + int i, j; + + vector_foreach_slot(mptable, mp1, i) { ++ /* drop invalid multipath configs */ ++ if (!mp1->wwid) { ++ condlog(0, "multipaths config section missing wwid"); ++ vector_del_slot(mptable, i--); ++ free_mpe(mp1); ++ continue; ++ } + j = i + 1; + vector_foreach_slot_after(mptable, mp2, j) { + if (strcmp(mp1->wwid, mp2->wwid)) +-- +2.17.2 + diff --git a/SOURCES/0047-tests-fix-missing-priority-blacklist-test.patch b/SOURCES/0047-tests-fix-missing-priority-blacklist-test.patch new file mode 100644 index 0000000..a73ffe6 --- /dev/null +++ b/SOURCES/0047-tests-fix-missing-priority-blacklist-test.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 16 Nov 2020 23:21:41 -0600 +Subject: [PATCH] tests: fix missing priority blacklist test + +Signed-off-by: Benjamin Marzinski +--- + tests/blacklist.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tests/blacklist.c b/tests/blacklist.c +index d20e97af..401600d9 100644 +--- a/tests/blacklist.c ++++ b/tests/blacklist.c +@@ -378,7 +378,6 @@ static void test_property_missing(void **state) + { + static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } }; + conf.blist_property = blist_property_wwn; +- expect_condlog(3, "sdb: blacklisted, udev property missing\n"); + assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"), + MATCH_NOTHING); + assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"), +-- +2.17.2 + diff --git a/SOURCES/0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch b/SOURCES/0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch new file mode 100644 index 0000000..fa9d703 --- /dev/null +++ b/SOURCES/0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 5 Nov 2020 09:15:43 -0600 +Subject: [PATCH] mpathpersist: Fix Register and Ignore with 0x00 SARK + +When the Register and Ignore command is run with sg_persist, if a 0x00 +Service Action Reservation Key is given or the --param-sark option is +not used at all, sg_persist will clear the registration. mpathpersist +will fail with an error. This patch fixes mpathpersist to work like +sg_persist in this case. + +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persist.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 3da7a6cf..aa196008 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -321,7 +321,8 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + } + + if (memcmp(paramp->key, &mpp->reservation_key, 8) && +- memcmp(paramp->sa_key, &mpp->reservation_key, 8)) { ++ memcmp(paramp->sa_key, &mpp->reservation_key, 8) && ++ (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) { + condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; +-- +2.17.2 + diff --git a/SOURCES/0049-mpathpersist-update-prkeys-file-on-changing-registra.patch b/SOURCES/0049-mpathpersist-update-prkeys-file-on-changing-registra.patch new file mode 100644 index 0000000..0cd0ab2 --- /dev/null +++ b/SOURCES/0049-mpathpersist-update-prkeys-file-on-changing-registra.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 23 Nov 2020 20:45:50 -0600 +Subject: [PATCH] mpathpersist: update prkeys file on changing registrations + +When the "reservation_key" option is set to "file" and Register command +is run with both the current Reservation Key and a new Service Action +Reservation Key, mpathpersist will change the registration, but will not +update the prkeys file. This means that future paths that come online +will not be able to register, since multipathd is still using the old +reservation key. Fix this. + +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persist.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index aa196008..a01dfb0b 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -307,9 +307,10 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + + memcpy(&prkey, paramp->sa_key, 8); + if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey && +- ((!get_be64(mpp->reservation_key) && +- rq_servact == MPATH_PROUT_REG_SA) || +- rq_servact == MPATH_PROUT_REG_IGN_SA)) { ++ (rq_servact == MPATH_PROUT_REG_IGN_SA || ++ (rq_servact == MPATH_PROUT_REG_SA && ++ (!get_be64(mpp->reservation_key) || ++ memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) { + memcpy(&mpp->reservation_key, paramp->sa_key, 8); + if (update_prkey_flags(alias, get_be64(mpp->reservation_key), + paramp->sa_flags)) { +-- +2.17.2 + diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index e479429..834cb8f 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.8.4 -Release: 5%{?dist} +Release: 6%{?dist} License: GPLv2 Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -49,6 +49,17 @@ Patch00035: 0035-Makefile.inc-trim-extra-information-from-systemd-ver.patch Patch00036: 0036-kpartx-fix-Wsign-compare-error.patch Patch00037: 0037-libmultipath-count-pending-paths-as-active-on-loads.patch Patch00038: 0038-multipath-deal-with-failures-flushing-maps.patch +Patch00039: 0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch +Patch00040: 0040-libmultipath-limit-reading-0xc9-vpd-page.patch +Patch00041: 0041-libmultipath-add-device-to-hwtable.c.patch +Patch00042: 0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch +Patch00043: 0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch +Patch00044: 0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch +Patch00045: 0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch +Patch00046: 0046-libmultipath-ignore-multipaths-sections-without-wwid.patch +Patch00047: 0047-tests-fix-missing-priority-blacklist-test.patch +Patch00048: 0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch +Patch00049: 0049-mpathpersist-update-prkeys-file-on-changing-registra.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -250,6 +261,35 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Nov 10 2020 Benjamin Marzinski 0.8.4-6 +- Add 0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch +- Add 0040-libmultipath-limit-reading-0xc9-vpd-page.patch + * Only check for rdac support on configured devices, or devices where + vpd page 0x00 indicates support for vpd page 0xc9 + * Fixes bz #1877415 +- Add 0041-libmultipath-add-device-to-hwtable.c.patch + * Add support for Fujitsu Eternus AB/HB + * Fixes bz #1857429 +- Add 0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch +- Add 0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch + * Fixes bz #1819897 +- Add 0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch + * Fixes bz #1875384 +- Add 0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch + * Fixes bz #1897530 +- Add 0046-libmultipath-ignore-multipaths-sections-without-wwid.patch + * Fixes bz #1897815 +- Add 0047-tests-fix-missing-priority-blacklist-test.patch +- Add 0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch + * Make mpathpersist Register and Ignore command clear the registration + with a 0x0 SARK, like sg_persist does. + * Fixes bz #1894103 +- Add 0049-mpathpersist-update-prkeys-file-on-changing-registra.patch + * Fixes bz #1900522 + * The above 11 patches have all been submitted upstream +- Resolves: bz #1819897, #1857429, #1875384, #1877415, #1894103, #1897530 +- Resolves: bz #1897815, #1900522 + * Mon Jul 13 2020 Benjamin Marzinski 0.8.4-5 - Add 0038-multipath-deal-with-failures-flushing-maps.patch * Don't print "fail" if multipath needs to failback to removing