diff --git a/SOURCES/0218-RHBZ-1510837-add-feature-fix.patch b/SOURCES/0218-RHBZ-1510837-add-feature-fix.patch new file mode 100644 index 0000000..e40abc8 --- /dev/null +++ b/SOURCES/0218-RHBZ-1510837-add-feature-fix.patch @@ -0,0 +1,25 @@ +--- + libmultipath/structs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Index: multipath-tools-130222/libmultipath/structs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.c ++++ multipath-tools-130222/libmultipath/structs.c +@@ -511,6 +511,16 @@ add_feature (char **f, char *n) + if (!n || *n == '0') + return 0; + ++ /* default feature is null */ ++ if (!*f) ++ { ++ l = asprintf(&t, "1 %s", n); ++ if (l == -1) ++ return 1; ++ *f = t; ++ return 0; ++ } ++ + /* Check if feature is already present */ + if (strstr(*f, n)) + return 0; diff --git a/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch b/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch new file mode 100644 index 0000000..5b2cbd1 --- /dev/null +++ b/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch @@ -0,0 +1,456 @@ +--- + libmultipath/config.c | 3 + + libmultipath/config.h | 3 + + libmultipath/configure.c | 2 + libmultipath/defaults.h | 1 + libmultipath/dict.c | 113 +++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/discovery.c | 44 +++++++++++++++++ + libmultipath/discovery.h | 1 + libmultipath/propsel.c | 26 ++++++++++ + libmultipath/propsel.h | 1 + libmultipath/structs.h | 8 ++- + multipath/multipath.conf.5 | 9 +++ + 11 files changed, 210 insertions(+), 1 deletion(-) + +Index: multipath-7.4.z/libmultipath/config.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/config.c ++++ multipath-7.4.z/libmultipath/config.c +@@ -347,6 +347,7 @@ merge_hwe (struct hwentry * dst, struct + merge_num(delay_wait_checks); + merge_num(skip_kpartx); + merge_num(max_sectors_kb); ++ merge_num(unpriv_sgio); + + /* + * Make sure features is consistent with +@@ -410,6 +411,7 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(delay_wait_checks); + overwrite_num(skip_kpartx); + overwrite_num(max_sectors_kb); ++ overwrite_num(unpriv_sgio); + + /* + * Make sure features is consistent with +@@ -690,6 +692,7 @@ load_config (char * file, struct udev *u + conf->remove_retries = 0; + conf->disable_changed_wwids = 0; + conf->max_sectors_kb = DEFAULT_MAX_SECTORS_KB; ++ conf->unpriv_sgio = DEFAULT_UNPRIV_SGIO; + + /* + * preload default hwtable +Index: multipath-7.4.z/libmultipath/config.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/config.h ++++ multipath-7.4.z/libmultipath/config.h +@@ -67,6 +67,7 @@ struct hwentry { + int delay_wait_checks; + int skip_kpartx; + int max_sectors_kb; ++ int unpriv_sgio; + char * bl_product; + }; + +@@ -95,6 +96,7 @@ struct mpentry { + int delay_wait_checks; + int skip_kpartx; + int max_sectors_kb; ++ int unpriv_sgio; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -153,6 +155,7 @@ struct config { + int remove_retries; + int disable_changed_wwids; + int max_sectors_kb; ++ int unpriv_sgio; + unsigned int version[3]; + + char * dev; +Index: multipath-7.4.z/libmultipath/configure.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/configure.c ++++ multipath-7.4.z/libmultipath/configure.c +@@ -297,6 +297,7 @@ setup_map (struct multipath * mpp, char + select_delay_wait_checks(mpp); + select_skip_kpartx(mpp); + select_max_sectors_kb(mpp); ++ select_unpriv_sgio(mpp); + + sysfs_set_scsi_tmo(mpp); + /* +@@ -721,6 +722,7 @@ domap (struct multipath * mpp, char * pa + } + } + dm_setgeometry(mpp); ++ sysfs_set_unpriv_sgio(mpp); + return DOMAP_OK; + } + return DOMAP_FAIL; +Index: multipath-7.4.z/libmultipath/defaults.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/defaults.h ++++ multipath-7.4.z/libmultipath/defaults.h +@@ -27,6 +27,7 @@ + #define DEFAULT_UEV_WAIT_TIMEOUT 30 + #define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF + #define DEFAULT_MAX_SECTORS_KB MAX_SECTORS_KB_UNDEF ++#define DEFAULT_UNPRIV_SGIO UNPRIV_SGIO_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-7.4.z/libmultipath/dict.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/dict.c ++++ multipath-7.4.z/libmultipath/dict.c +@@ -1015,6 +1015,28 @@ def_max_sectors_kb_handler(vector strvec + return 0; + } + ++static int ++def_unpriv_sgio_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->unpriv_sgio = UNPRIV_SGIO_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->unpriv_sgio = UNPRIV_SGIO_ON; ++ else ++ conf->unpriv_sgio = UNPRIV_SGIO_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -1851,6 +1873,33 @@ hw_max_sectors_kb_handler(vector strvec) + return 0; + } + ++static int ++hw_unpriv_sgio_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->unpriv_sgio = UNPRIV_SGIO_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->unpriv_sgio = UNPRIV_SGIO_ON; ++ else ++ hwe->unpriv_sgio = UNPRIV_SGIO_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * multipaths block handlers + */ +@@ -2422,6 +2471,32 @@ mp_max_sectors_kb_handler(vector strvec) + return 0; + } + ++static int ++mp_unpriv_sgio_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "0") == 0)) ++ mpe->unpriv_sgio = UNPRIV_SGIO_OFF; ++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "1") == 0)) ++ mpe->unpriv_sgio = UNPRIV_SGIO_ON; ++ else ++ mpe->unpriv_sgio = UNPRIV_SGIO_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * config file keywords printing + */ +@@ -2731,6 +2806,19 @@ snprint_mp_max_sectors_kb(char * buff, i + } + + static int ++snprint_mp_unpriv_sgio (char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->unpriv_sgio == UNPRIV_SGIO_UNDEF) ++ return 0; ++ else if (mpe->unpriv_sgio == UNPRIV_SGIO_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_hw_fast_io_fail(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -3132,6 +3220,19 @@ snprint_hw_max_sectors_kb(char * buff, i + } + + static int ++snprint_hw_unpriv_sgio(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->unpriv_sgio == UNPRIV_SGIO_ON) ++ return snprintf(buff, len, "yes"); ++ else if (hwe->unpriv_sgio == UNPRIV_SGIO_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return 0; ++} ++ ++static int + snprint_def_polling_interval (char * buff, int len, void * data) + { + return snprintf(buff, len, "%i", conf->checkint); +@@ -3617,6 +3718,15 @@ snprint_def_max_sectors_kb(char * buff, + } + + static int ++snprint_def_unpriv_sgio(char * buff, int len, void * data) ++{ ++ if (conf->unpriv_sgio == UNPRIV_SGIO_ON) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3699,6 +3809,7 @@ init_keywords(void) + install_keyword("remove_retries", &def_remove_retries_handler, &snprint_def_remove_retries); + install_keyword("disable_changed_wwids", &def_disable_changed_wwids_handler, &snprint_def_disable_changed_wwids); + install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb); ++ install_keyword("unpriv_sgio", &def_unpriv_sgio_handler, &snprint_def_unpriv_sgio); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +@@ -3769,6 +3880,7 @@ init_keywords(void) + install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks); + install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx); + install_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb); ++ install_keyword("unpriv_sgio", &hw_unpriv_sgio_handler, &snprint_hw_unpriv_sgio); + install_sublevel_end(); + + install_keyword_root("multipaths", &multipaths_handler); +@@ -3798,5 +3910,6 @@ init_keywords(void) + install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks); + install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx); + install_keyword("max_sectors_kb", &mp_max_sectors_kb_handler, &snprint_mp_max_sectors_kb); ++ install_keyword("unpriv_sgio", &mp_unpriv_sgio_handler, &snprint_mp_unpriv_sgio); + install_sublevel_end(); + } +Index: multipath-7.4.z/libmultipath/propsel.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/propsel.c ++++ multipath-7.4.z/libmultipath/propsel.c +@@ -944,3 +944,29 @@ select_max_sectors_kb (struct multipath + mp->max_sectors_kb = MAX_SECTORS_KB_UNDEF; + return 0; + } ++ ++extern int ++select_unpriv_sgio (struct multipath * mp) ++{ ++ if (mp->mpe && mp->mpe->unpriv_sgio != UNPRIV_SGIO_UNDEF) { ++ mp->unpriv_sgio = mp->mpe->unpriv_sgio; ++ condlog(3, "unpriv_sgio = %i (multipath setting)", ++ mp->unpriv_sgio); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->unpriv_sgio != UNPRIV_SGIO_UNDEF) { ++ mp->unpriv_sgio = mp->hwe->unpriv_sgio; ++ condlog(3, "unpriv_sgio = %i (controler setting)", ++ mp->unpriv_sgio); ++ return 0; ++ } ++ if (conf->unpriv_sgio != UNPRIV_SGIO_UNDEF) { ++ mp->unpriv_sgio = conf->unpriv_sgio; ++ condlog(3, "unpriv_sgio = %i (config file default)", ++ mp->unpriv_sgio); ++ return 0; ++ } ++ mp->unpriv_sgio = DEFAULT_UNPRIV_SGIO; ++ condlog(3, "unpriv_sgio = DISABLED (internal default)"); ++ return 0; ++} +Index: multipath-7.4.z/libmultipath/propsel.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/propsel.h ++++ multipath-7.4.z/libmultipath/propsel.h +@@ -26,3 +26,4 @@ int select_delay_watch_checks (struct mu + int select_delay_wait_checks (struct multipath * mp); + int select_skip_kpartx (struct multipath * mp); + int select_max_sectors_kb (struct multipath * mp); ++int select_unpriv_sgio (struct multipath * mp); +Index: multipath-7.4.z/libmultipath/structs.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/structs.h ++++ multipath-7.4.z/libmultipath/structs.h +@@ -134,12 +134,17 @@ enum skip_kpartx_states { + SKIP_KPARTX_ON, + }; + +- + enum max_sectors_kb_states { + MAX_SECTORS_KB_UNDEF = 0, + MAX_SECTORS_KB_MIN = 4, /* can't be smaller than page size */ + }; + ++enum unpriv_sgio_states { ++ UNPRIV_SGIO_UNDEF, ++ UNPRIV_SGIO_OFF, ++ UNPRIV_SGIO_ON, ++}; ++ + enum scsi_protocol { + SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ + SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ +@@ -260,6 +265,7 @@ struct multipath { + int skip_kpartx; + int max_sectors_kb; + int force_readonly; ++ int unpriv_sgio; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-7.4.z/libmultipath/discovery.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/discovery.c ++++ multipath-7.4.z/libmultipath/discovery.c +@@ -222,6 +222,50 @@ fail_reload: + } + + int ++sysfs_set_unpriv_sgio(struct multipath *mpp) ++{ ++ struct pathgroup * pgp; ++ struct path *pp; ++ int i, j, ret; ++ struct udev_device *udevice = NULL; ++ ++ if (mpp->unpriv_sgio != UNPRIV_SGIO_ON) ++ return 0; ++ if (!mpp->dmi && dm_get_info(mpp->alias, &mpp->dmi) != 0) { ++ condlog(0, "failed to get dm info on %s to set unpriv_sgio", ++ mpp->alias); ++ return 1; ++ } ++ udevice = udev_device_new_from_devnum(conf->udev, 'b', ++ makedev(mpp->dmi->major, ++ mpp->dmi->minor)); ++ if (!udevice) { ++ condlog(0, "failed to get udev device to set unpriv_sgio for %s", mpp->alias); ++ return 1; ++ } ++ ++ ret = sysfs_attr_set_value(udevice, "queue/unpriv_sgio", "1", 1); ++ udev_device_unref(udevice); ++ if (ret < 0) { ++ condlog(0, "failed setting unpriv_sgio on %s: %s", mpp->alias, ++ strerror(-ret)); ++ return 1; ++ } ++ ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ vector_foreach_slot (pgp->paths, pp, j) { ++ ret = sysfs_attr_set_value(pp->udev, ++ "queue/unpriv_sgio", "1", 1); ++ if (ret < 0) { ++ condlog(0, "failed setting unpriv_sgio on %s: %s", mpp->alias, strerror(-ret)); ++ return 1; ++ } ++ } ++ } ++ return 0; ++} ++ ++int + sysfs_get_timeout(struct path *pp, unsigned int *timeout) + { + const char *attr = NULL; +Index: multipath-7.4.z/libmultipath/discovery.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/discovery.h ++++ multipath-7.4.z/libmultipath/discovery.h +@@ -42,6 +42,7 @@ int store_pathinfo (vector pathvec, vect + struct path **pp_ptr); + int sysfs_set_scsi_tmo (struct multipath *mpp); + int sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload); ++int sysfs_set_unpriv_sgio(struct multipath *mpp); + int sysfs_get_timeout(struct path *pp, unsigned int *timeout); + int sysfs_get_host_pci_name(struct path *pp, char *pci_name); + int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address); +Index: multipath-7.4.z/multipath/multipath.conf.5 +=================================================================== +--- multipath-7.4.z.orig/multipath/multipath.conf.5 ++++ multipath-7.4.z/multipath/multipath.conf.5 +@@ -574,6 +574,11 @@ Between each attempt, multipath will sle + .B max_sectors_kb + Sets the max_sectors_kb device parameter on all path devices and the multipath + device to the specified value. Default is device dependent. ++.TP ++.B unpriv_sgio ++If set to \fIyes\fR, multipath will set upriv_sgio on the multipath device and ++all its paths, when it is created or reloaded. The default is ++.I no + . + .SH "blacklist section" + The +@@ -687,6 +692,8 @@ section: + .B skip_kpartx + .TP + .B max_sectors_kb ++.TP ++.B unpriv_sgio + .RE + .PD + .LP +@@ -789,6 +796,8 @@ section: + .B skip_kpartx + .TP + .B max_sectors_kb ++.TP ++.B unpriv_sgio + .RE + .PD + .LP diff --git a/SOURCES/0220-RHBZ-1510834-prkey.patch b/SOURCES/0220-RHBZ-1510834-prkey.patch new file mode 100644 index 0000000..ef37b6f --- /dev/null +++ b/SOURCES/0220-RHBZ-1510834-prkey.patch @@ -0,0 +1,1413 @@ +--- + libmpathpersist/mpath_persist.c | 79 +++++++++--------- + libmpathpersist/mpath_updatepr.c | 40 +++++---- + libmpathpersist/mpathpr.h | 5 - + libmultipath/Makefile | 2 + libmultipath/byteorder.h | 43 ++++++++++ + libmultipath/checkers/rbd.c | 16 --- + libmultipath/config.c | 9 +- + libmultipath/config.h | 9 +- + libmultipath/defaults.h | 1 + libmultipath/dict.c | 140 ++++++++++++-------------------- + libmultipath/prkey.c | 167 +++++++++++++++++++++++++++++++++++++++ + libmultipath/prkey.h | 19 ++++ + libmultipath/propsel.c | 58 ++++++------- + libmultipath/structs.h | 14 ++- + libmultipath/util.c | 34 +++++++ + libmultipath/util.h | 4 + mpathpersist/main.c | 5 - + multipath/multipath.conf.5 | 18 +++- + multipathd/cli.c | 7 + + multipathd/cli.h | 8 + + multipathd/cli_handlers.c | 69 ++++++++++++++++ + multipathd/cli_handlers.h | 4 + multipathd/main.c | 29 ++---- + multipathd/multipathd.8 | 13 +++ + 24 files changed, 576 insertions(+), 217 deletions(-) + +Index: multipath-7.4.z/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-7.4.z.orig/libmpathpersist/mpath_persist.c ++++ multipath-7.4.z/libmpathpersist/mpath_persist.c +@@ -221,9 +221,7 @@ int mpath_persistent_reserve_out ( int f + int map_present; + int major, minor; + int ret; +- int j; +- unsigned char *keyp; +- uint64_t prkey; ++ uint64_t prkey; + + conf->verbosity = verbose; + +@@ -290,6 +288,27 @@ int mpath_persistent_reserve_out ( int f + + select_reservation_key(mpp); + ++ 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)) { ++ memcpy(&mpp->reservation_key, paramp->sa_key, 8); ++ if (update_prkey(alias, get_be64(mpp->reservation_key))) { ++ condlog(0, "%s: failed to set prkey for multipathd.", ++ alias); ++ ret = MPATH_PR_DMMP_ERROR; ++ goto out1; ++ } ++ } ++ ++ if (memcmp(paramp->key, &mpp->reservation_key, 8) && ++ memcmp(paramp->sa_key, &mpp->reservation_key, 8)) { ++ condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out1; ++ } ++ + switch(rq_servact) + { + case MPATH_PROUT_REG_SA: +@@ -311,24 +330,19 @@ int mpath_persistent_reserve_out ( int f + } + + if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) || +- (rq_servact == MPATH_PROUT_REG_IGN_SA))) ++ (rq_servact == MPATH_PROUT_REG_IGN_SA))) + { +- keyp=paramp->sa_key; +- prkey = 0; +- for (j = 0; j < 8; ++j) { +- if (j > 0) +- prkey <<= 8; +- prkey |= *keyp; +- ++keyp; ++ if (!prkey) { ++ update_prflag(alias, 0); ++ update_prkey(alias, 0); + } +- if (prkey == 0) +- update_prflag(alias, "unset", noisy); + else +- update_prflag(alias, "set", noisy); ++ update_prflag(alias, 1); + } else { +- if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_CLEAR_SA) || +- (rq_servact == MPATH_PROUT_PREE_AB_SA ))){ +- update_prflag(alias, "unset", noisy); ++ if ((ret == MPATH_PR_SUCCESS) && ++ (rq_servact == MPATH_PROUT_CLEAR_SA)) { ++ update_prflag(alias, 0); ++ update_prkey(alias, 0); + } + } + out1: +@@ -729,8 +743,8 @@ int mpath_prout_rel(struct multipath *mp + goto out1; + } + +- if (mpp->reservation_key ){ +- memcpy (pamp->key, mpp->reservation_key, 8); ++ if (get_be64(mpp->reservation_key)){ ++ memcpy (pamp->key, &mpp->reservation_key, 8); + condlog (3, "%s: reservation key set.", mpp->wwid); + } + +@@ -741,9 +755,9 @@ int mpath_prout_rel(struct multipath *mp + pptr=pamp->trnptid_list[0]; + + for (i = 0; i < num; i++){ +- if (mpp->reservation_key && ++ if (get_be64(mpp->reservation_key) && + memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, +- mpp->reservation_key, 8)){ ++ &mpp->reservation_key, 8)){ + /*register with tarnsport id*/ + memset(pamp, 0, length); + pamp->trnptid_list[0] = pptr; +@@ -768,7 +782,7 @@ int mpath_prout_rel(struct multipath *mp + } + else + { +- if (mpp->reservation_key) ++ if (get_be64(mpp->reservation_key)) + found = 1; + } + +@@ -777,7 +791,7 @@ int mpath_prout_rel(struct multipath *mp + + if (found){ + memset (pamp, 0, length); +- memcpy (pamp->sa_key, mpp->reservation_key, 8); ++ memcpy (pamp->sa_key, &mpp->reservation_key, 8); + memset (pamp->key, 0, 8); + status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy); + } +@@ -826,11 +840,9 @@ int update_map_pr(struct multipath *mpp) + { + int noisy=0; + struct prin_resp *resp; +- int i,j, ret, isFound; +- unsigned char *keyp; +- uint64_t prkey; ++ int i, ret, isFound; + +- if (!mpp->reservation_key) ++ if (!get_be64(mpp->reservation_key)) + { + /* Nothing to do. Assuming pr mgmt feature is disabled*/ + condlog(3, "%s: reservation_key not set in multipath.conf", mpp->alias); +@@ -859,15 +871,8 @@ int update_map_pr(struct multipath *mpp) + return MPATH_PR_SUCCESS; + } + +- prkey = 0; +- keyp = mpp->reservation_key; +- for (j = 0; j < 8; ++j) { +- if (j > 0) +- prkey <<= 8; +- prkey |= *keyp; +- ++keyp; +- } +- condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias, prkey); ++ condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias, ++ get_be64(mpp->reservation_key)); + + isFound =0; + for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ ) +@@ -875,7 +880,7 @@ int update_map_pr(struct multipath *mpp) + condlog(2, "%s: PR IN READKEYS[%d] reservation key:", mpp->alias, i); + dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1); + +- if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8)) ++ if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8)) + { + condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias); + isFound =1; +Index: multipath-7.4.z/libmpathpersist/mpath_updatepr.c +=================================================================== +--- multipath-7.4.z.orig/libmpathpersist/mpath_updatepr.c ++++ multipath-7.4.z/libmpathpersist/mpath_updatepr.c +@@ -1,7 +1,7 @@ +-#include +-#include ++#include ++#include + #include +- ++#include + #include + #include + #include +@@ -18,10 +18,10 @@ + + unsigned long mem_allocated; /* Total memory used in Bytes */ + +-int update_prflag(char * arg1, char * arg2, int noisy) ++static int do_update_pr(char * mapname, char * arg) + { + int fd; +- char str[64]; ++ char str[256]; + char *reply; + int ret = 0; + +@@ -31,25 +31,35 @@ int update_prflag(char * arg1, char * ar + return 1 ; + } + +- snprintf(str,sizeof(str),"map %s %s", arg1, arg2); +- condlog (2, "%s: pr flag message=%s", arg1, str); ++ snprintf(str,sizeof(str),"map %s %s", mapname, arg); ++ condlog (2, "%s: pr message=%s", mapname, arg); + send_packet(fd, str); + ret = recv_packet(fd, &reply); + if (ret < 0) { +- condlog(2, "%s: message=%s recv error=%d", arg1, str, errno); ++ condlog(2, "%s: message=%s recv error=%d", mapname, str, errno); + ret = -2; + } else { +- condlog (2, "%s: message=%s reply=%s", arg1, str, reply); ++ condlog (2, "%s: message=%s reply=%s", mapname, str, reply); + if (!reply || strncmp(reply,"ok", 2) == 0) +- ret = -1; +- else if (strncmp(reply, "fail", 4) == 0) +- ret = -2; +- else{ +- ret = atoi(reply); +- } ++ ret = 0; ++ else ret = -1; + } + + free(reply); + mpath_disconnect(fd); + return ret; + } ++ ++int update_prflag(char *mapname, int set) { ++ return do_update_pr(mapname, (set)? "setprstatus" : "unsetprstatus"); ++} ++ ++int update_prkey(char *mapname, uint64_t prkey) { ++ char str[256]; ++ ++ if (prkey) ++ snprintf(str, sizeof(str), "setprkey key %" PRIx64, prkey); ++ else ++ snprintf(str, sizeof(str), "unsetprkey"); ++ return do_update_pr(mapname, str); ++} +Index: multipath-7.4.z/libmpathpersist/mpathpr.h +=================================================================== +--- multipath-7.4.z.orig/libmpathpersist/mpathpr.h ++++ multipath-7.4.z/libmpathpersist/mpathpr.h +@@ -1,6 +1,8 @@ + #ifndef MPATHPR_H + #define MPATHPR_H + ++#include ++ + struct prin_param { + char dev[FILE_NAME_SIZE]; + int rq_servact; +@@ -47,7 +49,8 @@ int mpath_prout_rel(struct multipath *mp + int send_prout_activepath(char * dev, int rq_servact, int rq_scope, + unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy); + +-int update_prflag(char * arg1, char * arg2, int noisy); ++int update_prflag(char *mapname, int set); ++int update_prkey(char *mapname, uint64_t prkey); + void * mpath_alloc_prin_response(int prin_sa); + int update_map_pr(struct multipath *mpp); + int devt2devname (char *devname, char *devt); +Index: multipath-7.4.z/libmultipath/byteorder.h +=================================================================== +--- /dev/null ++++ multipath-7.4.z/libmultipath/byteorder.h +@@ -0,0 +1,43 @@ ++#ifndef BYTEORDER_H_INCLUDED ++#define BYTEORDER_H_INCLUDED ++ ++#ifdef __linux__ ++# include ++# include ++#else ++# error unsupported ++#endif ++ ++#if BYTE_ORDER == LITTLE_ENDIAN ++# define le16_to_cpu(x) (x) ++# define be16_to_cpu(x) bswap_16(x) ++# define le32_to_cpu(x) (x) ++# define le64_to_cpu(x) (x) ++# define be32_to_cpu(x) bswap_32(x) ++# define be64_to_cpu(x) bswap_64(x) ++#elif BYTE_ORDER == BIG_ENDIAN ++# define le16_to_cpu(x) bswap_16(x) ++# define be16_to_cpu(x) (x) ++# define le32_to_cpu(x) bswap_32(x) ++# define le64_to_cpu(x) bswap_64(x) ++# define be32_to_cpu(x) (x) ++# define be64_to_cpu(x) (x) ++#else ++# error unsupported ++#endif ++ ++#define cpu_to_le16(x) le16_to_cpu(x) ++#define cpu_to_be16(x) be16_to_cpu(x) ++#define cpu_to_le32(x) le32_to_cpu(x) ++#define cpu_to_be32(x) be32_to_cpu(x) ++#define cpu_to_le64(x) le64_to_cpu(x) ++#define cpu_to_be64(x) be64_to_cpu(x) ++ ++struct be64 { ++ uint64_t _v; ++}; ++ ++#define get_be64(x) be64_to_cpu((x)._v) ++#define put_be64(x, y) do { (x)._v = cpu_to_be64(y); } while (0) ++ ++#endif /* BYTEORDER_H_INCLUDED */ +Index: multipath-7.4.z/libmultipath/checkers/rbd.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/checkers/rbd.c ++++ multipath-7.4.z/libmultipath/checkers/rbd.c +@@ -27,6 +27,7 @@ + + #include "../libmultipath/debug.h" + #include "../libmultipath/uevent.h" ++#include "../libmultipath/util.h" + + struct rbd_checker_context; + typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg); +@@ -355,21 +356,6 @@ int rbd_check(struct rbd_checker_context + return PATH_UP; + } + +-int safe_write(int fd, const void *buf, size_t count) +-{ +- while (count > 0) { +- ssize_t r = write(fd, buf, count); +- if (r < 0) { +- if (errno == EINTR) +- continue; +- return -errno; +- } +- count -= r; +- buf = (char *)buf + r; +- } +- return 0; +-} +- + static int sysfs_write_rbd_bus(const char *which, const char *buf, + size_t buf_len) + { +Index: multipath-7.4.z/libmultipath/config.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/config.c ++++ multipath-7.4.z/libmultipath/config.c +@@ -574,6 +574,9 @@ free_config (struct config * conf) + if (conf->wwids_file) + FREE(conf->wwids_file); + ++ if (conf->prkeys_file) ++ FREE(conf->prkeys_file); ++ + if (conf->prio_name) + FREE(conf->prio_name); + +@@ -589,9 +592,6 @@ free_config (struct config * conf) + if (conf->config_dir) + FREE(conf->config_dir); + +- if (conf->reservation_key) +- FREE(conf->reservation_key); +- + free_blacklist(conf->blist_devnode); + free_blacklist(conf->blist_wwid); + free_blacklist_device(conf->blist_device); +@@ -666,6 +666,7 @@ load_config (char * file, struct udev *u + get_sys_max_fds(&conf->max_fds); + conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); + conf->wwids_file = set_default(DEFAULT_WWIDS_FILE); ++ conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE); + conf->bindings_read_only = 0; + conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR); + conf->features = set_default(DEFAULT_FEATURES); +@@ -806,7 +807,7 @@ load_config (char * file, struct udev *u + conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE); + + if (!conf->multipath_dir || !conf->bindings_file || +- !conf->wwids_file) ++ !conf->wwids_file || !conf->prkeys_file) + goto out; + + if (conf->ignore_new_boot_devs) +Index: multipath-7.4.z/libmultipath/config.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/config.h ++++ multipath-7.4.z/libmultipath/config.h +@@ -3,6 +3,8 @@ + + #include + #include ++#include ++#include "byteorder.h" + + #define ORIGIN_DEFAULT 0 + #define ORIGIN_CONFIG 1 +@@ -80,7 +82,8 @@ struct mpentry { + + char * prio_name; + char * prio_args; +- unsigned char * reservation_key; ++ int prkey_source; ++ struct be64 reservation_key; + int pgpolicy; + int pgfailback; + int rr_weight; +@@ -167,12 +170,14 @@ struct config { + char * hwhandler; + char * bindings_file; + char * wwids_file; ++ char * prkeys_file; + char * prio_name; + char * prio_args; + char * checker_name; + char * alias_prefix; + char * config_dir; +- unsigned char * reservation_key; ++ int prkey_source; ++ struct be64 reservation_key; + + vector keywords; + vector mptable; +Index: multipath-7.4.z/libmultipath/defaults.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/defaults.h ++++ multipath-7.4.z/libmultipath/defaults.h +@@ -39,6 +39,7 @@ + #define DEFAULT_CONFIGFILE "/etc/multipath.conf" + #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" + #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" ++#define DEFAULT_PRKEYS_FILE "/etc/multipath/prkeys" + #define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d" + + char * set_default (char * str); +Index: multipath-7.4.z/libmultipath/dict.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/dict.c ++++ multipath-7.4.z/libmultipath/dict.c +@@ -20,6 +20,8 @@ + #include "defaults.h" + #include "prio.h" + #include "errno.h" ++#include "util.h" ++#include "prkey.h" + #include + + /* +@@ -554,46 +556,26 @@ static int + def_reservation_key_handler(vector strvec) + { + char *buff; +- char *tbuff; +- int j, k; +- int len; +- uint64_t prkey; ++ uint64_t prkey = 0; + + buff = set_value(strvec); + if (!buff) + return 1; + +- tbuff = buff; +- +- if (!memcmp("0x",buff, 2)) +- buff = buff + 2; +- +- len = strlen(buff); +- +- k = strspn(buff, "0123456789aAbBcCdDeEfF"); +- +- if (len != k) { +- FREE(tbuff); +- return 1; ++ if (strlen(buff) == 4 && !strcmp(buff, "file")) { ++ conf->prkey_source = PRKEY_SOURCE_FILE; ++ put_be64(conf->reservation_key, 0); ++ FREE(buff); ++ return 0; + } +- +- if (1 != sscanf (buff, "%" SCNx64 "", &prkey)) +- { +- FREE(tbuff); ++ else if (parse_prkey(buff, &prkey) != 0) { ++ FREE(buff); + return 1; + } + +- if (!conf->reservation_key) +- conf->reservation_key = (unsigned char *) malloc(8); +- +- memset(conf->reservation_key, 0, 8); +- +- for (j = 7; j >= 0; --j) { +- conf->reservation_key[j] = (prkey & 0xff); +- prkey >>= 8; +- } +- +- FREE(tbuff); ++ conf->prkey_source = PRKEY_SOURCE_CONF; ++ put_be64(conf->reservation_key, prkey); ++ FREE(buff); + return 0; + } + +@@ -668,6 +650,19 @@ wwids_file_handler(vector strvec) + } + + static int ++prkeys_file_handler(vector strvec) ++{ ++ if (conf->prkeys_file) ++ FREE(conf->prkeys_file); ++ conf->prkeys_file = set_value(strvec); ++ ++ if (!conf->prkeys_file) ++ return 1; ++ ++ return 0; ++} ++ ++static int + def_retain_hwhandler_handler(vector strvec) + { + char * buff; +@@ -2282,10 +2277,7 @@ static int + mp_reservation_key_handler (vector strvec) + { + char *buff; +- char *tbuff; + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); +- +- int j, k, len; + uint64_t prkey; + + if (!mpe) +@@ -2295,35 +2287,20 @@ mp_reservation_key_handler (vector strve + if (!buff) + return 1; + +- tbuff = buff; +- if (!memcmp(buff, "0x", 2)) +- buff = buff + 2; +- +- len = strlen(buff); +- +- k = strspn(buff, "0123456789aAbBcCdDeEfF"); +- if (len != k) { +- FREE(tbuff); +- return 1; ++ if (strlen(buff) == 4 && !strcmp(buff, "file")) { ++ mpe->prkey_source = PRKEY_SOURCE_FILE; ++ put_be64(mpe->reservation_key, 0); ++ FREE(buff); ++ return 0; + } +- +- if (1 != sscanf (buff, "%" SCNx64 "", &prkey)) +- { +- FREE(tbuff); ++ else if (parse_prkey(buff, &prkey) != 0) { ++ FREE(buff); + return 1; + } + +- if (!mpe->reservation_key) +- mpe->reservation_key = (unsigned char *) malloc(8); +- +- memset(mpe->reservation_key, 0, 8); +- +- for (j = 7; j >= 0; --j) { +- mpe->reservation_key[j] = (prkey & 0xff); +- prkey >>= 8; +- } +- +- FREE(tbuff); ++ mpe->prkey_source = PRKEY_SOURCE_CONF; ++ put_be64(mpe->reservation_key, prkey); ++ FREE(buff); + return 0; + } + +@@ -2714,22 +2691,14 @@ snprint_mp_prio_args(char * buff, int le + static int + snprint_mp_reservation_key (char * buff, int len, void * data) + { +- int i; +- unsigned char *keyp; +- uint64_t prkey = 0; + struct mpentry * mpe = (struct mpentry *)data; + +- if (!mpe->reservation_key) ++ if (mpe->prkey_source == PRKEY_SOURCE_NONE) + return 0; +- keyp = (unsigned char *)mpe->reservation_key; +- for (i = 0; i < 8; i++) { +- if (i > 0) +- prkey <<= 8; +- prkey |= *keyp; +- keyp++; +- } +- +- return snprintf(buff, len, "0x%" PRIx64, prkey); ++ if (mpe->prkey_source == PRKEY_SOURCE_FILE) ++ return snprintf(buff, len, "file"); ++ return snprintf(buff, len, "0x%" PRIx64, ++ get_be64(mpe->reservation_key)); + } + + static int +@@ -3551,22 +3520,22 @@ snprint_def_wwids_file (char * buff, int + } + + static int +-snprint_def_reservation_key(char * buff, int len, void * data) ++snprint_def_prkeys_file (char * buff, int len, void * data) + { +- int i; +- unsigned char *keyp; +- uint64_t prkey = 0; ++ if (conf->prkeys_file == NULL) ++ return 0; ++ return snprintf(buff, len, "%s", conf->prkeys_file); ++} + +- if (!conf->reservation_key) ++static int ++snprint_def_reservation_key(char * buff, int len, void * data) ++{ ++ if (conf->prkey_source == PRKEY_SOURCE_NONE) + return 0; +- keyp = (unsigned char *)conf->reservation_key; +- for (i = 0; i < 8; i++) { +- if (i > 0) +- prkey <<= 8; +- prkey |= *keyp; +- keyp++; +- } +- return snprintf(buff, len, "0x%" PRIx64, prkey); ++ if (conf->prkey_source == PRKEY_SOURCE_FILE) ++ return snprintf(buff, len, "file"); ++ return snprintf(buff, len, "0x%" PRIx64, ++ get_be64(conf->reservation_key)); + } + + static int +@@ -3788,6 +3757,7 @@ init_keywords(void) + install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); + install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file); + install_keyword("wwids_file", &wwids_file_handler, &snprint_def_wwids_file); ++ install_keyword("prkeys_file", &prkeys_file_handler, &snprint_def_prkeys_file); + install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); + install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); + install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths); +Index: multipath-7.4.z/libmultipath/prkey.c +=================================================================== +--- /dev/null ++++ multipath-7.4.z/libmultipath/prkey.c +@@ -0,0 +1,167 @@ ++#include "prkey.h" ++#include "structs.h" ++#include "file.h" ++#include "debug.h" ++#include "config.h" ++#include "util.h" ++#include "propsel.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define KEYSIZE 19 ++#define PRKEY_READ 0 ++#define PRKEY_WRITE 1 ++ ++static int do_prkey(int fd, char *wwid, char *keystr, int cmd) ++{ ++ char buf[4097]; ++ char *ptr; ++ off_t start = 0; ++ int bytes; ++ ++ while (1) { ++ if (lseek(fd, start, SEEK_SET) < 0) { ++ condlog(0, "prkey file read lseek failed : %s", ++ strerror(errno)); ++ return 1; ++ } ++ bytes = read(fd, buf, 4096); ++ if (bytes < 0) { ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ condlog(0, "failed to read from prkey file : %s", ++ strerror(errno)); ++ return 1; ++ } ++ if (!bytes) { ++ ptr = NULL; ++ break; ++ } ++ buf[bytes] = '\0'; ++ ptr = strstr(buf, wwid); ++ while (ptr) { ++ if (ptr == buf || *(ptr - 1) != ' ' || ++ *(ptr + strlen(wwid)) != '\n') ++ ptr = strstr(ptr + strlen(wwid), wwid); ++ else ++ break; ++ } ++ if (ptr) { ++ condlog(3, "found prkey for '%s'", wwid); ++ ptr[strlen(wwid)] = '\0'; ++ if (ptr - KEYSIZE < buf || ++ (ptr - KEYSIZE != buf && ++ *(ptr - KEYSIZE - 1) != '\n')) { ++ condlog(0, "malformed prkey file line for wwid: '%s'", ptr); ++ return 1; ++ } ++ ptr = ptr - KEYSIZE; ++ break; ++ } ++ ptr = strrchr(buf, '\n'); ++ if (ptr == NULL) { ++ condlog(4, "couldn't file newline, assuming end of file"); ++ break; ++ } ++ start = start + (ptr - buf) + 1; ++ } ++ if (cmd == PRKEY_READ) { ++ if (!ptr || *ptr == '#') ++ return 1; ++ memcpy(keystr, ptr, KEYSIZE - 1); ++ keystr[KEYSIZE - 1] = '\0'; ++ return 0; ++ } ++ if (!ptr && !keystr) ++ return 0; ++ if (ptr) { ++ if (lseek(fd, start + (ptr - buf), SEEK_SET) < 0) { ++ condlog(0, "prkey write lseek failed : %s", ++ strerror(errno)); ++ return 1; ++ } ++ } ++ if (!keystr) { ++ if (safe_write(fd, "#", 1) < 0) { ++ condlog(0, "failed to write to prkey file : %s", ++ strerror(errno)); ++ return 1; ++ } ++ return 0; ++ } ++ if (!ptr) { ++ if (lseek(fd, 0, SEEK_END) < 0) { ++ condlog(0, "prkey write lseek failed : %s", ++ strerror(errno)); ++ return 1; ++ } ++ } ++ bytes = sprintf(buf, "%s %s\n", keystr, wwid); ++ if (safe_write(fd, buf, bytes) < 0) { ++ condlog(0, "failed to write to prkey file: %s", ++ strerror(errno)); ++ return 1; ++ } ++ return 0; ++} ++ ++int get_prkey(struct multipath *mpp, uint64_t *prkey) ++{ ++ int fd; ++ int unused; ++ int ret = 1; ++ char keystr[KEYSIZE]; ++ ++ if (!strlen(mpp->wwid)) ++ goto out; ++ ++ fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER); ++ if (fd < 0) ++ goto out; ++ ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ); ++ if (ret) ++ goto out_file; ++ ret = !!parse_prkey(keystr, prkey); ++out_file: ++ close(fd); ++out: ++ return ret; ++} ++ ++int set_prkey(struct multipath *mpp, uint64_t prkey) ++{ ++ int fd; ++ int can_write = 1; ++ int ret = 1; ++ char keystr[KEYSIZE]; ++ ++ if (!strlen(mpp->wwid)) ++ goto out; ++ ++ fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER); ++ if (fd < 0) ++ goto out; ++ if (!can_write) { ++ condlog(0, "cannot set prkey, prkeys file is read-only"); ++ goto out_file; ++ } ++ if (prkey) { ++ snprintf(keystr, KEYSIZE, "0x%016" PRIx64, prkey); ++ keystr[KEYSIZE - 1] = '\0'; ++ ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_WRITE); ++ } ++ else ++ ret = do_prkey(fd, mpp->wwid, NULL, PRKEY_WRITE); ++ if (ret == 0) ++ select_reservation_key(mpp); ++ if (get_be64(mpp->reservation_key) != prkey) ++ ret = 1; ++out_file: ++ close(fd); ++out: ++ return ret; ++} +Index: multipath-7.4.z/libmultipath/prkey.h +=================================================================== +--- /dev/null ++++ multipath-7.4.z/libmultipath/prkey.h +@@ -0,0 +1,19 @@ ++#ifndef _PRKEY_H ++#define _PRKEY_H ++ ++#include "structs.h" ++#include ++ ++#define PRKEYS_FILE_HEADER \ ++"# Multipath persistent reservation keys, Version : 1.0\n" \ ++"# NOTE: this file is automatically maintained by the multipathd program.\n" \ ++"# You should not need to edit this file in normal circumstances.\n" \ ++"#\n" \ ++"# Format:\n" \ ++"# prkey wwid\n" \ ++"#\n" ++ ++int set_prkey(struct multipath *mpp, uint64_t prkey); ++int get_prkey(struct multipath *mpp, uint64_t *prkey); ++ ++#endif /* _PRKEY_H */ +Index: multipath-7.4.z/libmultipath/propsel.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/propsel.c ++++ multipath-7.4.z/libmultipath/propsel.c +@@ -18,6 +18,7 @@ + #include "prio.h" + #include "discovery.h" + #include "prioritizers/alua_rtpg.h" ++#include "prkey.h" + #include + + pgpolicyfn *pgpolicies[] = { +@@ -711,44 +712,39 @@ select_flush_on_last_del(struct multipat + extern int + select_reservation_key (struct multipath * mp) + { +- int j; +- unsigned char *keyp; +- uint64_t prkey = 0; +- +- mp->reservation_key = NULL; +- +- if (mp->mpe && mp->mpe->reservation_key) { +- keyp = mp->mpe->reservation_key; +- for (j = 0; j < 8; ++j) { +- if (j > 0) +- prkey <<= 8; +- prkey |= *keyp; +- ++keyp; +- } +- +- condlog(3, "%s: reservation_key = 0x%" PRIx64 " " +- "(multipath setting)", mp->alias, prkey); ++ uint64_t prkey; ++ char *origin = NULL; ++ char *from_file = ""; + ++ if (mp->mpe && mp->mpe->prkey_source != PRKEY_SOURCE_NONE) { ++ mp->prkey_source = mp->mpe->prkey_source; + mp->reservation_key = mp->mpe->reservation_key; +- return 0; ++ origin = "multipath setting"; ++ goto out; + } + +- if (conf->reservation_key) { +- keyp = conf->reservation_key; +- for (j = 0; j < 8; ++j) { +- if (j > 0) +- prkey <<= 8; +- prkey |= *keyp; +- ++keyp; +- } +- +- condlog(3, "%s: reservation_key = 0x%" PRIx64 +- " (config file default)", mp->alias, prkey); +- ++ if (conf->prkey_source != PRKEY_SOURCE_NONE) { ++ mp->prkey_source = conf->prkey_source; + mp->reservation_key = conf->reservation_key; +- return 0; ++ origin = "config file default"; ++ goto out; + } + ++ put_be64(mp->reservation_key, 0); ++ mp->prkey_source = PRKEY_SOURCE_NONE; ++ return 0; ++out: ++ if (mp->prkey_source == PRKEY_SOURCE_FILE) { ++ from_file = " (from prkeys file)"; ++ if (get_prkey(mp, &prkey) != 0) ++ put_be64(mp->reservation_key, 0); ++ else ++ put_be64(mp->reservation_key, prkey); ++ } ++ if (get_be64(mp->reservation_key)) ++ condlog(0, "%s: reservation_key = 0x%" PRIx64 " (%s)%s", ++ mp->alias, get_be64(mp->reservation_key), origin, ++ from_file); + return 0; + } + +Index: multipath-7.4.z/libmultipath/structs.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/structs.h ++++ multipath-7.4.z/libmultipath/structs.h +@@ -2,8 +2,10 @@ + #define _STRUCTS_H + + #include ++#include + + #include "prio.h" ++#include "byteorder.h" + + #define WWID_SIZE 128 + #define SERIAL_SIZE 65 +@@ -27,7 +29,6 @@ + #define NO_PATH_RETRY_FAIL -1 + #define NO_PATH_RETRY_QUEUE -2 + +- + enum free_path_mode { + KEEP_PATHS, + FREE_PATHS +@@ -169,6 +170,12 @@ enum missing_udev_info_states { + INFO_REQUESTED, + }; + ++enum prkey_sources { ++ PRKEY_SOURCE_NONE, ++ PRKEY_SOURCE_CONF, ++ PRKEY_SOURCE_FILE, ++}; ++ + struct sg_id { + int host_no; + int channel; +@@ -298,8 +305,9 @@ struct multipath { + /* checkers shared data */ + void * mpcontext; + +- /* persistent management data*/ +- unsigned char * reservation_key; ++ /* persistent management data */ ++ int prkey_source; ++ struct be64 reservation_key; + unsigned char prflag; + }; + +Index: multipath-7.4.z/libmultipath/util.c +=================================================================== +--- multipath-7.4.z.orig/libmultipath/util.c ++++ multipath-7.4.z/libmultipath/util.c +@@ -5,12 +5,14 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "memory.h" + #include "checkers.h" + #include "vector.h" + #include "structs.h" ++#include "util.h" + + void + strchop(char *str) +@@ -297,3 +299,35 @@ int in_initrd(void) { + + return saved; + } ++ ++int parse_prkey(char *ptr, uint64_t *prkey) ++{ ++ if (!ptr) ++ return 1; ++ if (*ptr == '0') ++ ptr++; ++ if (*ptr == 'x' || *ptr == 'X') ++ ptr++; ++ if (*ptr == '\0' || strlen(ptr) > 16) ++ return 1; ++ if (strlen(ptr) != strspn(ptr, "0123456789aAbBcCdDeEfF")) ++ return 1; ++ if (sscanf(ptr, "%" SCNx64 "", prkey) != 1) ++ return 1; ++ return 0; ++} ++ ++int safe_write(int fd, const void *buf, size_t count) ++{ ++ while (count > 0) { ++ ssize_t r = write(fd, buf, count); ++ if (r < 0) { ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ return -errno; ++ } ++ count -= r; ++ buf = (char *)buf + r; ++ } ++ return 0; ++} +Index: multipath-7.4.z/libmultipath/util.h +=================================================================== +--- multipath-7.4.z.orig/libmultipath/util.h ++++ multipath-7.4.z/libmultipath/util.h +@@ -1,6 +1,8 @@ + #ifndef _UTIL_H + #define _UTIL_H + ++#include ++ + void strchop(char *); + int basenamecpy (const char * src, char * dst, int); + int filepresent (char * run); +@@ -12,6 +14,8 @@ int devt2devname (char *, int, char *); + dev_t parse_devt(const char *dev_t); + char *convert_dev(char *dev, int is_path_device); + int in_initrd(void); ++int parse_prkey(char *ptr, uint64_t *prkey); ++int safe_write(int fd, const void *buf, size_t count); + + #define safe_sprintf(var, format, args...) \ + snprintf(var, sizeof(var), format, ##args) >= sizeof(var) +Index: multipath-7.4.z/multipathd/cli.c +=================================================================== +--- multipath-7.4.z.orig/multipathd/cli.c ++++ multipath-7.4.z/multipathd/cli.c +@@ -190,6 +190,10 @@ load_keys (void) + r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0); + r += add_key(keys, "format", FMT, 1); + r += add_key(keys, "json", JSON, 0); ++ r += add_key(keys, "getprkey", GETPRKEY, 0); ++ r += add_key(keys, "setprkey", SETPRKEY, 0); ++ r += add_key(keys, "unsetprkey", UNSETPRKEY, 0); ++ r += add_key(keys, "key", KEY, 1); + + if (r) { + free_keys(keys); +@@ -506,6 +510,9 @@ cli_init (void) { + add_handler(GETPRSTATUS+MAP, NULL); + add_handler(SETPRSTATUS+MAP, NULL); + add_handler(UNSETPRSTATUS+MAP, NULL); ++ add_handler(GETPRKEY+MAP, NULL); ++ add_handler(SETPRKEY+MAP+KEY, NULL); ++ add_handler(UNSETPRKEY+MAP, NULL); + add_handler(FORCEQ+DAEMON, NULL); + add_handler(RESTOREQ+DAEMON, NULL); + +Index: multipath-7.4.z/multipathd/cli.h +=================================================================== +--- multipath-7.4.z.orig/multipathd/cli.h ++++ multipath-7.4.z/multipathd/cli.h +@@ -37,6 +37,10 @@ enum { + __UNSETPRSTATUS, + __FMT, + __JSON, ++ __GETPRKEY, ++ __SETPRKEY, ++ __UNSETPRKEY, ++ __KEY, + }; + + #define LIST (1 << __LIST) +@@ -76,6 +80,10 @@ enum { + #define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS) + #define FMT (1ULL << __FMT) + #define JSON (1ULL << __JSON) ++#define GETPRKEY (1ULL << __GETPRKEY) ++#define SETPRKEY (1ULL << __SETPRKEY) ++#define UNSETPRKEY (1ULL << __UNSETPRKEY) ++#define KEY (1ULL << __KEY) + + #define INITIAL_REPLY_LEN 1200 + +Index: multipath-7.4.z/multipathd/cli_handlers.c +=================================================================== +--- multipath-7.4.z.orig/multipathd/cli_handlers.c ++++ multipath-7.4.z/multipathd/cli_handlers.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "main.h" + #include "cli.h" +@@ -1232,3 +1233,71 @@ cli_unsetprstatus(void * v, char ** repl + + return 0; + } ++ ++int ++cli_getprkey(void * v, char ** reply, int * len, void * data) ++{ ++ struct multipath * mpp; ++ struct vectors * vecs = (struct vectors *)data; ++ char *mapname = get_keyparam(v, MAP); ++ ++ mapname = convert_dev(mapname, 0); ++ condlog(3, "%s: get persistent reservation key (operator)", mapname); ++ mpp = find_mp_by_str(vecs->mpvec, mapname); ++ ++ if (!mpp) ++ return 1; ++ ++ *reply = malloc(20); ++ ++ if (!get_be64(mpp->reservation_key)) { ++ sprintf(*reply, "none\n"); ++ *len = strlen(*reply) + 1; ++ return 0; ++ } ++ snprintf(*reply, 20, "0x%" PRIx64 "\n", ++ get_be64(mpp->reservation_key)); ++ (*reply)[19] = '\0'; ++ *len = strlen(*reply) + 1; ++ return 0; ++} ++ ++int ++cli_unsetprkey(void * v, char ** reply, int * len, void * data) ++{ ++ struct multipath * mpp; ++ struct vectors * vecs = (struct vectors *)data; ++ char *mapname = get_keyparam(v, MAP); ++ ++ mapname = convert_dev(mapname, 0); ++ condlog(3, "%s: unset persistent reservation key (operator)", mapname); ++ mpp = find_mp_by_str(vecs->mpvec, mapname); ++ ++ if (!mpp) ++ return 1; ++ ++ return set_prkey(mpp, 0); ++} ++ ++int cli_setprkey(void * v, char ** reply, int * len, void * data) ++{ ++ struct multipath * mpp; ++ struct vectors * vecs = (struct vectors *)data; ++ char *mapname = get_keyparam(v, MAP); ++ char *keyparam = get_keyparam(v, KEY); ++ uint64_t prkey; ++ ++ mapname = convert_dev(mapname, 0); ++ condlog(3, "%s: set persistent reservation key (operator)", mapname); ++ mpp = find_mp_by_str(vecs->mpvec, mapname); ++ ++ if (!mpp) ++ return 1; ++ ++ if (parse_prkey(keyparam, &prkey) != 0) { ++ condlog(0, "%s: invalid prkey : '%s'", mapname, keyparam); ++ return 1; ++ } ++ ++ return set_prkey(mpp, prkey); ++} +Index: multipath-7.4.z/multipathd/cli_handlers.h +=================================================================== +--- multipath-7.4.z.orig/multipathd/cli_handlers.h ++++ multipath-7.4.z/multipathd/cli_handlers.h +@@ -42,4 +42,6 @@ int cli_reassign (void * v, char ** repl + int cli_getprstatus(void * v, char ** reply, int * len, void * data); + int cli_setprstatus(void * v, char ** reply, int * len, void * data); + 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); +Index: multipath-7.4.z/multipathd/main.c +=================================================================== +--- multipath-7.4.z.orig/multipathd/main.c ++++ multipath-7.4.z/multipathd/main.c +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + + #include "main.h" + #include "pidfile.h" +@@ -1050,6 +1051,9 @@ uxlsnrloop (void * ap) + set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus); + set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus); + set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus); ++ 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(FORCEQ+DAEMON, cli_force_no_daemon_q); + set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q); + +@@ -2266,10 +2270,8 @@ main (int argc, char *argv[]) + void * mpath_pr_event_handler_fn (void * pathp ) + { + struct multipath * mpp; +- int i,j, ret, isFound; ++ int i, ret, isFound; + struct path * pp = (struct path *)pathp; +- unsigned char *keyp; +- uint64_t prkey; + struct prout_param_descriptor *param; + struct prin_resp *resp; + +@@ -2297,22 +2299,15 @@ void * mpath_pr_event_handler_fn (void + ret = MPATH_PR_SUCCESS; + goto out; + } +- prkey = 0; +- keyp = (unsigned char *)mpp->reservation_key; +- for (j = 0; j < 8; ++j) { +- if (j > 0) +- prkey <<= 8; +- prkey |= *keyp; +- ++keyp; +- } +- condlog(2, "Multipath reservation_key: 0x%" PRIx64 " ", prkey); ++ condlog(2, "Multipath reservation_key: 0x%" PRIx64 " ", ++ get_be64(mpp->reservation_key)); + + isFound =0; + for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ ) + { + condlog(2, "PR IN READKEYS[%d] reservation key:",i); + dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , -1); +- if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8)) ++ if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8)) + { + condlog(2, "%s: pr key found in prin readkeys response", mpp->alias); + isFound =1; +@@ -2329,11 +2324,7 @@ void * mpath_pr_event_handler_fn (void + + param= malloc(sizeof(struct prout_param_descriptor)); + memset(param, 0 , sizeof(struct prout_param_descriptor)); +- +- for (j = 7; j >= 0; --j) { +- param->sa_key[j] = (prkey & 0xff); +- prkey >>= 8; +- } ++ memcpy(param->sa_key, &mpp->reservation_key, 8); + param->num_transportid = 0; + + condlog(3, "device %s:%s", pp->dev, pp->mpp->wwid); +@@ -2360,7 +2351,7 @@ int mpath_pr_event_handle(struct path *p + + mpp = pp->mpp; + +- if (!mpp->reservation_key) ++ if (!get_be64(mpp->reservation_key)) + return -1; + + pthread_attr_init(&attr); +Index: multipath-7.4.z/libmultipath/Makefile +=================================================================== +--- multipath-7.4.z.orig/libmultipath/Makefile ++++ multipath-7.4.z/libmultipath/Makefile +@@ -16,7 +16,7 @@ OBJS = memory.o parser.o vector.o devmap + pgpolicies.o debug.o regex.o defaults.o uevent.o \ + switchgroup.o uxsock.o print.o alias.o log_pthread.o \ + log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \ +- lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o ++ lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o + + LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h) + +Index: multipath-7.4.z/multipath/multipath.conf.5 +=================================================================== +--- multipath-7.4.z.orig/multipath/multipath.conf.5 ++++ multipath-7.4.z/multipath/multipath.conf.5 +@@ -414,6 +414,13 @@ of the wwids for LUNs it has created mul + Defaults to + .I /etc/multipath/wwids + .TP ++.B prkeys_file ++The full pathname of the prkeys file, which is used by multipathd to keep ++track of the reservation key used for a specific WWID, when ++\fIreservation_key\fR is set to \fIfile\fR. ++Defaults to ++.I /etc/multipath/prkeys ++.TP + .B log_checker_err + If set to + .I once +@@ -428,7 +435,16 @@ This is the service action reservation k + set for all multipath devices using persistent reservations, and it must be + the same as the RESERVATION KEY field of the PERSISTENT RESERVE OUT parameter + list which contains an 8-byte value provided by the application client to the +-device server to identify the I_T nexus. It is unset by default. ++device server to identify the I_T nexus. ++.RS ++.PP ++Alternatively, this can be set to \fBfile\fR, which will store the RESERVATION ++KEY registered by mpathpersist in the \fIprkeys_file\fR. multipathd will then ++use this key to register additional paths as they appear. When the ++registration is removed, the RESERVATION KEY is removed from the ++\fIprkeys_file\fR. ++It is unset by default. ++.RE + .TP + .B retain_attached_hw_handler + If set to +Index: multipath-7.4.z/multipathd/multipathd.8 +=================================================================== +--- multipath-7.4.z.orig/multipathd/multipathd.8 ++++ multipath-7.4.z/multipathd/multipathd.8 +@@ -155,6 +155,19 @@ Disable persistent reservation managemen + .B map|multipath $map getprstatus + Get the current persistent reservation management status of $map + .TP ++.B map|multipath $map getprkey ++Get the current persistent reservation key associated with $map. ++.TP ++.B map|multipath $map setprkey key $key ++Set the persistent reservation key associated with $map to $key in the ++\fIprkeys_file\fR. This key will only be used by multipathd if ++\fIreservation_key\fR is set to \fIfile\fR in \fI/etc/multipath.conf\fR. ++.TP ++.B map|multipath $map unsetprkey ++Remove the persistent reservation key associated with $map from the ++\fIprkeys_file\fR. This will only unset the key used by multipathd if ++\fIreservation_key\fR is set to \fIfile\fR in \fI/etc/multipath.conf\fR. ++.TP + .B quit|exit + End interactive session. + .TP +Index: multipath-7.4.z/mpathpersist/main.c +=================================================================== +--- multipath-7.4.z.orig/mpathpersist/main.c ++++ multipath-7.4.z/mpathpersist/main.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -139,7 +140,7 @@ int main (int argc, char * argv[]) + ++num_prout_param; + break; + case 'K': +- if (1 != sscanf (optarg, "%" SCNx64 "", ¶m_rk)) ++ if (parse_prkey(optarg, ¶m_rk) != 0) + { + fprintf (stderr, "bad argument to '--param-rk'\n"); + return MPATH_PR_SYNTAX_ERROR; +@@ -148,7 +149,7 @@ int main (int argc, char * argv[]) + break; + + case 'S': +- if (1 != sscanf (optarg, "%" SCNx64 "", ¶m_sark)) ++ if (parse_prkey(optarg, ¶m_sark) != 0) + { + fprintf (stderr, "bad argument to '--param-sark'\n"); + return MPATH_PR_SYNTAX_ERROR; diff --git a/SOURCES/0221-RHBZ-1510839-nimble-config.patch b/SOURCES/0221-RHBZ-1510839-nimble-config.patch new file mode 100644 index 0000000..96c9985 --- /dev/null +++ b/SOURCES/0221-RHBZ-1510839-nimble-config.patch @@ -0,0 +1,20 @@ +--- + libmultipath/hwtable.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1125,9 +1125,10 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + .pgfailback = -FAILBACK_IMMEDIATE, ++ .checker_name = TUR, + .selector = "round-robin 0", + .dev_loss = MAX_DEV_LOSS_TMO, +- .fast_io_fail = 1, ++ .fast_io_fail = 5, + }, + { + .vendor = "XtremIO", diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index d5e21a2..7443479 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.4.9 -Release: 111%{?dist} +Release: 111%{?dist}.2 License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -224,6 +224,10 @@ Patch0214: 0214-RHBZ-1392115-set-paths-not-ready.patch Patch0215: 0215-RHBZ-1444194-fix-check-partitions.patch Patch0216: 0216-RHBZ-1448562-fix-reserve.patch Patch0217: 0217-RHBZ-1448576-3PAR-config.patch +Patch0218: 0218-RHBZ-1510837-add-feature-fix.patch +Patch0219: 0219-RHBZ-1510834-unpriv-sgio.patch +Patch0220: 0220-RHBZ-1510834-prkey.patch +Patch0221: 0221-RHBZ-1510839-nimble-config.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -528,6 +532,10 @@ device-mapper-multipath's libdmmp C API library %patch0215 -p1 %patch0216 -p1 %patch0217 -p1 +%patch0218 -p1 +%patch0219 -p1 +%patch0220 -p1 +%patch0221 -p1 cp %{SOURCE1} . %build @@ -652,6 +660,23 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_pkgconfdir}/libdmmp.pc %changelog +* Mon Nov 20 2017 Benjamin Marzinski 0.4.9-111.2 +- Modify Add 0220-RHBZ-1510834-prkey.patch + * Improve error checking for mpathpersist +- Resolves: bz #1510834 + +* Wed Nov 8 2017 Benjamin Marzinski 0.4.9-111.1 +- Add 0218-RHBZ-1510837-add-feature-fix.patch + * handle null feature string +- Add 0219-RHBZ-1510834-unpriv-sgio.patch + * add unpriv_sgio configuration option to set unpriv_sgio on multipath device + and paths +- Add 0220-RHBZ-1510834-prkey.patch + * allow setting reservation_key to "file" to set and read keys from + prkey_file. Also add new multipathd commands to modify the prkey file. +- Add 0221-RHBZ-1510839-nimble-config.patch +- Resolves: bz #1510834, #1510837, #1510839 + * Mon May 15 2017 Benjamin Marzinski 0.4.9-111 - Remove 0217-RHBZ-1437329-blacklist-oracle-devs.patch * Incorrect change, and the bug is already fixed.