From 45d01a1f8bed835b15b5f7c83979fbcf49151044 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 10 2018 05:36:46 +0000 Subject: import device-mapper-multipath-0.4.9-119.el7 --- diff --git a/SOURCES/0191-RHBZ-1169168-disable-changed-paths.patch b/SOURCES/0191-RHBZ-1169168-disable-changed-paths.patch index e7e9286..4c1eb6b 100644 --- a/SOURCES/0191-RHBZ-1169168-disable-changed-paths.patch +++ b/SOURCES/0191-RHBZ-1169168-disable-changed-paths.patch @@ -1,12 +1,13 @@ --- - libmultipath/config.c | 1 + - libmultipath/config.h | 1 + - libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ - libmultipath/discovery.c | 11 ++++++----- - libmultipath/discovery.h | 1 + - libmultipath/structs.h | 1 + - multipathd/main.c | 26 ++++++++++++++++++++++++++ - 7 files changed, 69 insertions(+), 5 deletions(-) + libmultipath/config.c | 1 + + libmultipath/config.h | 1 + + libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ + libmultipath/discovery.c | 11 ++++++----- + libmultipath/discovery.h | 1 + + libmultipath/structs.h | 1 + + multipath/multipath.conf.5 | 6 ++++++ + multipathd/main.c | 26 ++++++++++++++++++++++++++ + 8 files changed, 75 insertions(+), 5 deletions(-) Index: multipath-tools-130222/libmultipath/discovery.c =================================================================== @@ -208,3 +209,20 @@ Index: multipath-tools-130222/libmultipath/dict.c __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); +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -557,6 +557,12 @@ regular filesystem, the device will be r + default is + .I no + .TP ++.B disable_changed_wwids ++If set to \fIyes\fR, multipathd will check the path wwid on change events, and ++if it has changed from the wwid of the multipath device, multipathd will ++disable access to the path until the wwid changes back. The default is ++.I no ++.TP + .B remove_retries + This sets how may times multipath will retry removing a device that is in-use. + Between each attempt, multipath will sleep 1 second. The default is diff --git a/SOURCES/0197-RHBZ-1394059-max-sectors-kb.patch b/SOURCES/0197-RHBZ-1394059-max-sectors-kb.patch index 7ed778d..f5cfa23 100644 --- a/SOURCES/0197-RHBZ-1394059-max-sectors-kb.patch +++ b/SOURCES/0197-RHBZ-1394059-max-sectors-kb.patch @@ -414,7 +414,7 @@ Index: multipath-tools-130222/multipath/multipath.conf.5 =================================================================== --- multipath-tools-130222.orig/multipath/multipath.conf.5 +++ multipath-tools-130222/multipath/multipath.conf.5 -@@ -561,6 +561,10 @@ default is +@@ -567,6 +567,10 @@ disable access to the path until the wwi This sets how may times multipath will retry removing a device that is in-use. Between each attempt, multipath will sleep 1 second. The default is .I 0 @@ -425,7 +425,7 @@ Index: multipath-tools-130222/multipath/multipath.conf.5 . .SH "blacklist section" The -@@ -672,6 +676,8 @@ section: +@@ -678,6 +682,8 @@ section: .B delay_wait_checks .TP .B skip_kpartx @@ -434,7 +434,7 @@ Index: multipath-tools-130222/multipath/multipath.conf.5 .RE .PD .LP -@@ -772,6 +778,8 @@ section: +@@ -778,6 +784,8 @@ section: .B delay_wait_checks .TP .B skip_kpartx diff --git a/SOURCES/0205-RHBZ-1416569-reset-stats.patch b/SOURCES/0205-RHBZ-1416569-reset-stats.patch index bb414ba..b152f88 100644 --- a/SOURCES/0205-RHBZ-1416569-reset-stats.patch +++ b/SOURCES/0205-RHBZ-1416569-reset-stats.patch @@ -3,7 +3,8 @@ multipathd/cli_handlers.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ multipathd/cli_handlers.h | 2 ++ multipathd/main.c | 2 ++ - 4 files changed, 50 insertions(+) + multipathd/multipathd.8 | 6 ++++++ + 5 files changed, 56 insertions(+) Index: multipath-tools-130222/multipathd/cli.c =================================================================== @@ -106,3 +107,20 @@ Index: multipath-tools-130222/multipathd/main.c set_handler_callback(ADD+PATH, cli_add_path); set_handler_callback(DEL+PATH, cli_del_path); set_handler_callback(ADD+MAP, cli_add_map); +Index: multipath-tools-130222/multipathd/multipathd.8 +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.8 ++++ multipath-tools-130222/multipathd/multipathd.8 +@@ -87,6 +87,12 @@ Show all available block devices by name + .B list|show status + Show the number of path checkers in each possible state, the number of monitored paths, and whether multipathd is currently handling a uevent. + .TP ++.B reset maps|multipaths stats ++Reset the stat counters for all multipath devices. ++.TP ++.B reset map|multipath $map stats ++Reset the stat counters for a specific multipath device. ++.TP + .B add path $path + Add a path to the list of monitored paths. $path is as listed in /sys/block (e.g. sda). + .TP diff --git a/SOURCES/0218-RHBZ-1459370-add-feature-fix.patch b/SOURCES/0218-RHBZ-1459370-add-feature-fix.patch new file mode 100644 index 0000000..e40abc8 --- /dev/null +++ b/SOURCES/0218-RHBZ-1459370-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/0218-RHBZ-1510837-add-feature-fix.patch b/SOURCES/0218-RHBZ-1510837-add-feature-fix.patch deleted file mode 100644 index e40abc8..0000000 --- a/SOURCES/0218-RHBZ-1510837-add-feature-fix.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- - 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-1448970-fix-resize.patch b/SOURCES/0219-RHBZ-1448970-fix-resize.patch new file mode 100644 index 0000000..b753119 --- /dev/null +++ b/SOURCES/0219-RHBZ-1448970-fix-resize.patch @@ -0,0 +1,149 @@ +--- + libmultipath/configure.c | 18 +++------------ + libmultipath/devmapper.c | 55 +++++++++++++++++++++++++++++++++++++++++------ + libmultipath/devmapper.h | 3 +- + 3 files changed, 55 insertions(+), 21 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -616,7 +616,6 @@ extern int + domap (struct multipath * mpp, char * params) + { + int r = 0; +- uint16_t udev_flags = ((mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG) | ((mpp->skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0) | ((mpp->nr_active)? 0 : MPATH_UDEV_NO_PATHS_FLAG); + + /* + * last chance to quit before touching the devmaps +@@ -660,17 +659,11 @@ domap (struct multipath * mpp, char * pa + break; + + case ACT_RELOAD: +- r = dm_addmap_reload(mpp, params); +- if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, +- udev_flags); ++ r = dm_addmap_reload(mpp, params, 0); + break; + + case ACT_RESIZE: +- r = dm_addmap_reload(mpp, params); +- if (r) +- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, +- udev_flags); ++ r = dm_addmap_reload(mpp, params, 1); + break; + + case ACT_RENAME: +@@ -679,11 +672,8 @@ domap (struct multipath * mpp, char * pa + + case ACT_RENAME2: + r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx); +- if (r) { +- r = dm_addmap_reload(mpp, params); +- if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, udev_flags); +- } ++ if (r) ++ r = dm_addmap_reload(mpp, params, 0); + break; + + default: +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -356,15 +356,33 @@ dm_addmap_create (struct multipath *mpp, + #define ADDMAP_RO 1 + + extern int +-dm_addmap_reload (struct multipath *mpp, char *params) { ++dm_addmap_reload (struct multipath *mpp, char *params, int flush) { ++ int r = 0; ++ uint16_t udev_flags = ((mpp->force_udev_reload)? ++ 0 : MPATH_UDEV_RELOAD_FLAG) | ++ ((mpp->skip_kpartx == SKIP_KPARTX_ON)? ++ MPATH_UDEV_NO_KPARTX_FLAG : 0) | ++ ((mpp->nr_active)? 0 : MPATH_UDEV_NO_PATHS_FLAG); ++ + sysfs_set_max_sectors_kb(mpp, 1); +- if (!mpp->force_readonly) { +- if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF)) +- return 1; +- if (errno != EROFS) ++ if (!mpp->force_readonly) ++ r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ++ ADDMAP_RW, SKIP_KPARTX_OFF); ++ if (!r) { ++ if (!mpp->force_readonly && errno != EROFS) + return 0; ++ r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ++ ADDMAP_RO, SKIP_KPARTX_OFF); + } +- return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO, SKIP_KPARTX_OFF); ++ if (r) ++ r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, ++ 1, udev_flags, 0); ++ if (r) ++ return r; ++ if (dm_is_suspended(mpp->alias)) ++ dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, 1, ++ udev_flags, 0); ++ return 0; + } + + extern int +@@ -613,6 +631,31 @@ dm_is_mpath(const char * name) + out: + dm_task_destroy(dmt); + return r; ++} ++ ++int ++dm_is_suspended(const char *mapname) ++{ ++ int r = -1; ++ struct dm_task *dmt; ++ struct dm_info info; ++ ++ if (!(dmt = dm_task_create(DM_DEVICE_INFO))) ++ return r; ++ ++ if (!dm_task_set_name(dmt, mapname)) ++ goto out; ++ ++ if (!dm_task_run(dmt)) ++ goto out; ++ ++ if (!dm_task_get_info(dmt, &info) || !info.exists) ++ goto out; ++ ++ r = info.suspended; ++out: ++ dm_task_destroy(dmt); ++ return r; + } + + static int +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -30,7 +30,7 @@ int dm_drv_version (unsigned int * versi + int dm_simplecmd_flush (int, const char *, int, uint16_t); + int dm_simplecmd_noflush (int, const char *, uint16_t); + int dm_addmap_create (struct multipath *mpp, char *params); +-int dm_addmap_reload (struct multipath *mpp, char *params); ++int dm_addmap_reload (struct multipath *mpp, char *params, int flush); + int dm_map_present (const char *); + int dm_get_map(const char *, unsigned long long *, char *); + int dm_get_status(char *, char *); +@@ -51,6 +51,7 @@ int dm_switchgroup(char * mapname, int i + int dm_enablegroup(char * mapname, int index); + int dm_disablegroup(char * mapname, int index); + int dm_get_maps (vector mp); ++int dm_is_suspended(const char *mapname); + int dm_geteventnr (char *name); + int dm_get_major (char *name); + int dm_get_minor (char *name); diff --git a/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch b/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch deleted file mode 100644 index 5b2cbd1..0000000 --- a/SOURCES/0219-RHBZ-1510834-unpriv-sgio.patch +++ /dev/null @@ -1,456 +0,0 @@ ---- - 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-1448223-fix-kpartx.patch b/SOURCES/0220-RHBZ-1448223-fix-kpartx.patch new file mode 100644 index 0000000..3061a2f --- /dev/null +++ b/SOURCES/0220-RHBZ-1448223-fix-kpartx.patch @@ -0,0 +1,58 @@ +--- + kpartx/kpartx.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -114,10 +114,13 @@ set_delimiter (char * device, char * del + { + char * p = device; + +- while (*(p++) != 0x0) ++ if (*p == 0x0) ++ return; ++ ++ while (*(++p) != 0x0) + continue; + +- if (isdigit(*(p - 2))) ++ if (isdigit(*(p - 1))) + *delimiter = 'p'; + } + +@@ -136,15 +139,17 @@ strip_slash (char * device) + static int + find_devname_offset (char * device) + { +- char *p, *q = NULL; ++ char *p, *q; + +- p = device; ++ q = p = device; + +- while (*p++) ++ while (*p) { + if (*p == '/') +- q = p; ++ q = p + 1; ++ p++; ++ } + +- return (int)(q - device) + 1; ++ return (int)(q - device); + } + + static char * +@@ -343,6 +348,10 @@ main(int argc, char **argv){ + } + device = loopdev; + } ++ else if (!S_ISBLK(buf.st_mode)) { ++ fprintf(stderr, "invalid device: %s\n", device); ++ exit(1); ++ } + + off = find_devname_offset(device); + diff --git a/SOURCES/0220-RHBZ-1510834-prkey.patch b/SOURCES/0220-RHBZ-1510834-prkey.patch deleted file mode 100644 index ef37b6f..0000000 --- a/SOURCES/0220-RHBZ-1510834-prkey.patch +++ /dev/null @@ -1,1413 +0,0 @@ ---- - 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-RH-harden-files.patch b/SOURCES/0221-RH-harden-files.patch new file mode 100644 index 0000000..46099d0 --- /dev/null +++ b/SOURCES/0221-RH-harden-files.patch @@ -0,0 +1,101 @@ +--- + Makefile.inc | 2 +- + kpartx/Makefile | 4 ++-- + libmpathpersist/Makefile | 2 +- + mpathpersist/Makefile | 4 ++-- + multipath/Makefile | 4 ++-- + multipathd/Makefile | 2 +- + 6 files changed, 9 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/Makefile.inc +=================================================================== +--- multipath-tools-130222.orig/Makefile.inc ++++ multipath-tools-130222/Makefile.inc +@@ -48,7 +48,7 @@ ifndef RPM_OPT_FLAGS + RPM_OPT_FLAGS = -O2 -g -pipe -Wformat-security -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 + endif + +-LDFLAGS += -Wl,-z,relro ++LDFLAGS += -Wl,-z,relro -Wl,-z,now + OPTFLAGS = $(RPM_OPT_FLAGS) -Wunused -Wstrict-prototypes + CFLAGS = $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" + SHARED_FLAGS = -shared +Index: multipath-tools-130222/kpartx/Makefile +=================================================================== +--- multipath-tools-130222.orig/kpartx/Makefile ++++ multipath-tools-130222/kpartx/Makefile +@@ -4,7 +4,7 @@ + # + include ../Makefile.inc + +-CFLAGS += -fPIC -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ++CFLAGS += -fPIE -DPIE -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + + LIBDM_API_COOKIE = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_set_cookie' /usr/include/libdevmapper.h) + +@@ -12,7 +12,7 @@ ifneq ($(strip $(LIBDM_API_COOKIE)),0) + CFLAGS += -DLIBDM_API_COOKIE + endif + +-LDFLAGS = -ldevmapper ++LDFLAGS += -ldevmapper -pie + OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \ + gpt.o mac.o ps3.o crc32.o lopart.o xstrncpy.o devmapper.o + EXEC = kpartx +Index: multipath-tools-130222/libmpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/Makefile ++++ multipath-tools-130222/libmpathpersist/Makefile +@@ -21,7 +21,7 @@ all: $(LIBS) + + $(LIBS): + $(CC) -Wall -c $(CFLAGS) *.c +- $(CC) -shared $(LIBDEPS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) ++ $(CC) $(LDFLAGS) -shared $(LIBDEPS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) + ln -s $(LIBS) $(DEVLIB) + $(GZIP) mpath_persistent_reserve_in.3 > mpath_persistent_reserve_in.3.gz + $(GZIP) mpath_persistent_reserve_out.3 > mpath_persistent_reserve_out.3.gz +Index: multipath-tools-130222/mpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/Makefile ++++ multipath-tools-130222/mpathpersist/Makefile +@@ -4,8 +4,8 @@ include ../Makefile.inc + + OBJS = main.o + +-CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) +-LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -L$(mpathcmddir) -lmpathcmd -lmultipath -ludev ++CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathpersistdir) ++LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -L$(mpathcmddir) -lmpathcmd -lmultipath -ludev -pie + + EXEC = mpathpersist + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -6,9 +6,9 @@ include ../Makefile.inc + + OBJS = main.o + +-CFLAGS += -I$(multipathdir) -I$(mpathcmddir) ++CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathcmddir) + LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath -ludev \ +- -L$(mpathcmddir) -lmpathcmd ++ -L$(mpathcmddir) -lmpathcmd -pie + + EXEC = multipath + +Index: multipath-tools-130222/multipathd/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipathd/Makefile ++++ multipath-tools-130222/multipathd/Makefile +@@ -8,7 +8,7 @@ include ../Makefile.inc + CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir) + LDFLAGS += -lpthread -ldevmapper -lreadline -ludev -ldl \ + -L$(multipathdir) -lmultipath -L$(mpathpersistdir) -lmpathpersist \ +- -L$(mpathcmddir) -lmpathcmd -Wl,-z,now -pie ++ -L$(mpathcmddir) -lmpathcmd -pie + + # + # debuging stuff diff --git a/SOURCES/0221-RHBZ-1510839-nimble-config.patch b/SOURCES/0221-RHBZ-1510839-nimble-config.patch deleted file mode 100644 index 96c9985..0000000 --- a/SOURCES/0221-RHBZ-1510839-nimble-config.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- - 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/SOURCES/0222-RHBZ-1457288-fix-show-maps-json.patch b/SOURCES/0222-RHBZ-1457288-fix-show-maps-json.patch new file mode 100644 index 0000000..90f37b8 --- /dev/null +++ b/SOURCES/0222-RHBZ-1457288-fix-show-maps-json.patch @@ -0,0 +1,23 @@ +--- + multipathd/cli_handlers.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -133,10 +133,12 @@ show_maps_json (char ** r, int * len, st + struct multipath * mpp; + char * c; + char * reply; +- unsigned int maxlen = INITIAL_REPLY_LEN * +- PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec); ++ unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; + ++ if (VECTOR_SIZE(vecs->mpvec) > 0) ++ maxlen *= PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec); ++ + vector_foreach_slot(vecs->mpvec, mpp, i) { + if (update_multipath(vecs, mpp->alias, 0)) { + return 1; diff --git a/SOURCES/0223-RHBZ-1452210-unpriv-sgio.patch b/SOURCES/0223-RHBZ-1452210-unpriv-sgio.patch new file mode 100644 index 0000000..7a5b4b1 --- /dev/null +++ b/SOURCES/0223-RHBZ-1452210-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-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/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); + /* +@@ -711,6 +712,7 @@ domap (struct multipath * mpp, char * pa + } + } + dm_setgeometry(mpp); ++ sysfs_set_unpriv_sgio(mpp); + return DOMAP_OK; + } + return DOMAP_FAIL; +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/discovery.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.h ++++ multipath-tools-130222/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-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -580,6 +580,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 +@@ -693,6 +698,8 @@ section: + .B skip_kpartx + .TP + .B max_sectors_kb ++.TP ++.B unpriv_sgio + .RE + .PD + .LP +@@ -795,6 +802,8 @@ section: + .B skip_kpartx + .TP + .B max_sectors_kb ++.TP ++.B unpriv_sgio + .RE + .PD + .LP diff --git a/SOURCES/0224-RHBZ-1452210-prkey.patch b/SOURCES/0224-RHBZ-1452210-prkey.patch new file mode 100644 index 0000000..e981971 --- /dev/null +++ b/SOURCES/0224-RHBZ-1452210-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-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/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-tools-130222/libmpathpersist/mpath_updatepr.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_updatepr.c ++++ multipath-tools-130222/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-tools-130222/libmpathpersist/mpathpr.h +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpathpr.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/byteorder.h +=================================================================== +--- /dev/null ++++ multipath-tools-130222/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-tools-130222/libmultipath/checkers/rbd.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/rbd.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/prkey.c +=================================================================== +--- /dev/null ++++ multipath-tools-130222/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-tools-130222/libmultipath/prkey.h +=================================================================== +--- /dev/null ++++ multipath-tools-130222/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-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/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-tools-130222/libmultipath/util.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/util.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.h ++++ multipath-tools-130222/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-tools-130222/multipathd/cli.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.c ++++ multipath-tools-130222/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-tools-130222/multipathd/cli.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.h ++++ multipath-tools-130222/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-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "main.h" + #include "cli.h" +@@ -1234,3 +1235,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-tools-130222/multipathd/cli_handlers.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.h ++++ multipath-tools-130222/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-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/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-tools-130222/libmultipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/Makefile ++++ multipath-tools-130222/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-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/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-tools-130222/multipathd/multipathd.8 +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.8 ++++ multipath-tools-130222/multipathd/multipathd.8 +@@ -161,6 +161,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-tools-130222/mpathpersist/main.c +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.c ++++ multipath-tools-130222/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/0225-RH-udevdir.patch b/SOURCES/0225-RH-udevdir.patch new file mode 100644 index 0000000..b3c891f --- /dev/null +++ b/SOURCES/0225-RH-udevdir.patch @@ -0,0 +1,46 @@ +--- + Makefile.inc | 2 +- + multipath/Makefile | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -24,9 +24,9 @@ install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ +- $(INSTALL_PROGRAM) -d $(DESTDIR)/usr/lib/udev/rules.d +- $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules +- $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules ++ $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)/rules.d ++ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules ++ $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(libudevdir)/rules.d/11-dm-mpath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -34,8 +34,8 @@ install: + $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(mandir) + + uninstall: +- rm $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules +- rm $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules ++ rm $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules ++ rm $(DESTDIR)$(libudevdir)/rules.d/11-dm-mpath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) + rm $(DESTDIR)$(bindir)/mpathconf + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz +Index: multipath-tools-130222/Makefile.inc +=================================================================== +--- multipath-tools-130222.orig/Makefile.inc ++++ multipath-tools-130222/Makefile.inc +@@ -24,7 +24,7 @@ endif + prefix = + exec_prefix = $(prefix) + bindir = $(exec_prefix)/usr/sbin +-libudevdir = ${prefix}/lib/udev ++libudevdir = ${prefix}/usr/lib/udev + multipathdir = $(TOPDIR)/libmultipath + mandir = $(prefix)/usr/share/man/man8 + man5dir = $(prefix)/usr/share/man/man5 diff --git a/SOURCES/0226-RH-allow-overrides-section.patch b/SOURCES/0226-RH-allow-overrides-section.patch new file mode 100644 index 0000000..6b1dec1 --- /dev/null +++ b/SOURCES/0226-RH-allow-overrides-section.patch @@ -0,0 +1,64 @@ +--- + libmultipath/dict.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -3721,6 +3721,18 @@ snprint_bled_product (char * buff, int l + + #define __deprecated + ++static int ++nop_handler(vector strvec) ++{ ++ return 0; ++} ++ ++static int ++snprint_nop(char * buff, int len, void * data) ++{ ++ return 0; ++} ++ + void + init_keywords(void) + { +@@ -3853,6 +3865,36 @@ init_keywords(void) + install_keyword("unpriv_sgio", &hw_unpriv_sgio_handler, &snprint_hw_unpriv_sgio); + install_sublevel_end(); + ++ install_keyword_root("overrides", &nop_handler); ++ install_keyword("path_grouping_policy", &nop_handler, &snprint_nop); ++ install_keyword("uid_attribute", &nop_handler, &snprint_nop); ++ install_keyword("path_selector", &nop_handler, &snprint_nop); ++ install_keyword("path_checker", &nop_handler, &snprint_nop); ++ install_keyword("checker", &nop_handler, &snprint_nop); ++ install_keyword("alias_prefix", &nop_handler, &snprint_nop); ++ install_keyword("features", &nop_handler, &snprint_nop); ++ install_keyword("hardware_handler", &nop_handler, &snprint_nop); ++ install_keyword("prio", &nop_handler, &snprint_nop); ++ install_keyword("prio_args", &nop_handler, &snprint_nop); ++ install_keyword("failback", &nop_handler, &snprint_nop); ++ install_keyword("rr_weight", &nop_handler, &snprint_nop); ++ install_keyword("no_path_retry", &nop_handler, &snprint_nop); ++ install_keyword("rr_min_io", &nop_handler, &snprint_nop); ++ install_keyword("rr_min_io_rq", &nop_handler, &snprint_nop); ++ install_keyword("pg_timeout", &nop_handler, &snprint_nop); ++ install_keyword("flush_on_last_del", &nop_handler, &snprint_nop); ++ install_keyword("fast_io_fail_tmo", &nop_handler, &snprint_nop); ++ install_keyword("dev_loss_tmo", &nop_handler, &snprint_nop); ++ install_keyword("user_friendly_names", &nop_handler, &snprint_nop); ++ install_keyword("retain_attached_hw_handler", &nop_handler, &snprint_nop); ++ install_keyword("detect_prio", &nop_handler, &snprint_nop); ++ install_keyword("detect_path_checker", &nop_handler, &snprint_nop); ++ install_keyword("deferred_remove", &nop_handler, &snprint_nop); ++ install_keyword("delay_watch_checks", &nop_handler, &snprint_nop); ++ install_keyword("delay_wait_checks", &nop_handler, &snprint_nop); ++ install_keyword("skip_kpartx", &nop_handler, &snprint_nop); ++ install_keyword("max_sectors_kb", &nop_handler, &snprint_nop); ++ + install_keyword_root("multipaths", &multipaths_handler); + install_keyword_multi("multipath", &multipath_handler, NULL); + install_sublevel(); diff --git a/SOURCES/0227-RHBZ-1465773-fix-path-delay-msg.patch b/SOURCES/0227-RHBZ-1465773-fix-path-delay-msg.patch new file mode 100644 index 0000000..ed24a17 --- /dev/null +++ b/SOURCES/0227-RHBZ-1465773-fix-path-delay-msg.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -538,7 +538,7 @@ ev_add_path (struct path * pp, struct ve + pp->tpgs == TPGS_IMPLICIT)) + mpp->force_udev_reload = 1; + else { +- condlog(2, "%s : delaying path addition until %s is fully initialized", pp->dev, mpp->alias); ++ condlog(2, "%s [%s]: delaying path addition until %s is fully initialized", pp->dev, pp->dev_t, mpp->alias); + mpp->wait_for_udev = 2; + orphan_path(pp); + return 0; diff --git a/SOURCES/0228-RHBZ-1464634-hauwei-config-update.patch b/SOURCES/0228-RHBZ-1464634-hauwei-config-update.patch new file mode 100644 index 0000000..a72c39b --- /dev/null +++ b/SOURCES/0228-RHBZ-1464634-hauwei-config-update.patch @@ -0,0 +1,22 @@ +--- + libmultipath/hwtable.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1163,9 +1163,12 @@ static struct hwentry default_hw[] = { + .product = "XSG1", + .features = DEFAULT_FEATURES, + .hwhandler = DEFAULT_HWHANDLER, +- .pgpolicy = MULTIBUS, ++ .pgpolicy = GROUP_BY_PRIO, ++ .prio_name = PRIO_ALUA, ++ .prio_args = NULL, + .pgfailback = -FAILBACK_IMMEDIATE, + .checker_name = TUR, ++ .dev_loss = 30, + }, + { + /* diff --git a/SOURCES/0229-RHBZ-1467987-poll-on-udev-monitor.patch b/SOURCES/0229-RHBZ-1467987-poll-on-udev-monitor.patch new file mode 100644 index 0000000..46723d7 --- /dev/null +++ b/SOURCES/0229-RHBZ-1467987-poll-on-udev-monitor.patch @@ -0,0 +1,38 @@ +--- + libmultipath/uevent.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +Index: multipath-tools-130222/libmultipath/uevent.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.c ++++ multipath-tools-130222/libmultipath/uevent.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + #include "memory.h" + #include "debug.h" +@@ -460,6 +461,21 @@ int uevent_listen(struct udev *udev) + struct uevent *uev; + struct udev_device *dev; + struct udev_list_entry *list_entry; ++ struct pollfd ev_poll; ++ int fdcount; ++ ++ memset(&ev_poll, 0, sizeof(struct pollfd)); ++ ev_poll.fd = fd; ++ ev_poll.events = POLLIN; ++ errno = 0; ++ fdcount = poll(&ev_poll, 1, -1); ++ if (fdcount <= 0 || !(ev_poll.revents & POLLIN)) { ++ if (!errno || errno == EINTR) ++ continue; ++ condlog(0, "error receiving uevent message"); ++ err = -errno; ++ break; ++ } + + dev = udev_monitor_receive_device(monitor); + if (!dev) { diff --git a/SOURCES/0230-UP-allow-invalid-creates.patch b/SOURCES/0230-UP-allow-invalid-creates.patch new file mode 100644 index 0000000..6f6cb4d --- /dev/null +++ b/SOURCES/0230-UP-allow-invalid-creates.patch @@ -0,0 +1,81 @@ +--- + libmultipath/devmapper.c | 31 +++++++++++++++++++++---------- + 1 file changed, 21 insertions(+), 10 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -264,12 +264,15 @@ dm_device_remove (const char *name, int + + static int + dm_addmap (int task, const char *target, struct multipath *mpp, char * params, +- int use_uuid, int ro, int skip_kpartx) { ++ int use_uuid, int ro, uint16_t udev_flags) { + int r = 0; + struct dm_task *dmt; + char *prefixed_uuid = NULL; + uint32_t cookie = 0; +- uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); ++ ++ /* Need to add this here to allow 0 to be passed in udev_flags */ ++ if (conf->daemon) ++ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK; + + if (!(dmt = dm_task_create (task))) + return 0; +@@ -326,16 +329,28 @@ dm_addmap (int task, const char *target, + return r; + } + ++static uint16_t build_udev_flags(const struct multipath *mpp, int reload) ++{ ++ /* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */ ++ return (mpp->skip_kpartx == SKIP_KPARTX_ON ? ++ MPATH_UDEV_NO_KPARTX_FLAG : 0) | ++ (mpp->nr_active == 0 ? ++ MPATH_UDEV_NO_PATHS_FLAG : 0) | ++ (reload && !mpp->force_udev_reload ? ++ MPATH_UDEV_RELOAD_FLAG : 0); ++} ++ + extern int + dm_addmap_create (struct multipath *mpp, char * params) { + int ro; ++ uint16_t udev_flags = build_udev_flags(mpp, 0); + + sysfs_set_max_sectors_kb(mpp, 0); + for (ro = 0; ro <= 1; ro++) { + int err; + + if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, +- mpp, params, 1, ro, mpp->skip_kpartx)) ++ mpp, params, 1, ro, udev_flags)) + return 1; + /* + * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. +@@ -358,21 +373,17 @@ dm_addmap_create (struct multipath *mpp, + extern int + dm_addmap_reload (struct multipath *mpp, char *params, int flush) { + int r = 0; +- uint16_t udev_flags = ((mpp->force_udev_reload)? +- 0 : MPATH_UDEV_RELOAD_FLAG) | +- ((mpp->skip_kpartx == SKIP_KPARTX_ON)? +- MPATH_UDEV_NO_KPARTX_FLAG : 0) | +- ((mpp->nr_active)? 0 : MPATH_UDEV_NO_PATHS_FLAG); ++ uint16_t udev_flags = build_udev_flags(mpp, 1); + + sysfs_set_max_sectors_kb(mpp, 1); + if (!mpp->force_readonly) + r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, +- ADDMAP_RW, SKIP_KPARTX_OFF); ++ ADDMAP_RW, 0); + if (!r) { + if (!mpp->force_readonly && errno != EROFS) + return 0; + r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, +- ADDMAP_RO, SKIP_KPARTX_OFF); ++ ADDMAP_RO, 0); + } + if (r) + r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, diff --git a/SOURCES/0231-RHBZ-1458852-delay-readying.patch b/SOURCES/0231-RHBZ-1458852-delay-readying.patch new file mode 100644 index 0000000..953fd3c --- /dev/null +++ b/SOURCES/0231-RHBZ-1458852-delay-readying.patch @@ -0,0 +1,489 @@ +--- + libmultipath/config.c | 4 + + libmultipath/config.h | 3 + + libmultipath/defaults.h | 1 + libmultipath/devmapper.c | 19 ++++++-- + libmultipath/dict.c | 104 +++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/propsel.c | 26 +++++++++++ + libmultipath/propsel.h | 1 + libmultipath/structs.h | 7 +++ + multipath/multipath.conf.5 | 13 +++++ + multipath/multipath.rules | 1 + multipathd/main.c | 27 +++++++++++ + 11 files changed, 202 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -348,6 +348,7 @@ merge_hwe (struct hwentry * dst, struct + merge_num(skip_kpartx); + merge_num(max_sectors_kb); + merge_num(unpriv_sgio); ++ merge_num(ghost_delay); + + /* + * Make sure features is consistent with +@@ -412,6 +413,7 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(skip_kpartx); + overwrite_num(max_sectors_kb); + overwrite_num(unpriv_sgio); ++ overwrite_num(ghost_delay); + + /* + * Make sure features is consistent with +@@ -482,6 +484,7 @@ store_hwe (vector hwtable, struct hwentr + hwe->retain_hwhandler = dhwe->retain_hwhandler; + hwe->detect_prio = dhwe->detect_prio; + hwe->detect_checker = dhwe->detect_checker; ++ hwe->ghost_delay = dhwe->ghost_delay; + + if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product))) + goto out; +@@ -694,6 +697,7 @@ load_config (char * file, struct udev *u + conf->disable_changed_wwids = 0; + conf->max_sectors_kb = DEFAULT_MAX_SECTORS_KB; + conf->unpriv_sgio = DEFAULT_UNPRIV_SGIO; ++ conf->ghost_delay = DEFAULT_GHOST_DELAY; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -70,6 +70,7 @@ struct hwentry { + int skip_kpartx; + int max_sectors_kb; + int unpriv_sgio; ++ int ghost_delay; + char * bl_product; + }; + +@@ -100,6 +101,7 @@ struct mpentry { + int skip_kpartx; + int max_sectors_kb; + int unpriv_sgio; ++ int ghost_delay; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -159,6 +161,7 @@ struct config { + int disable_changed_wwids; + int max_sectors_kb; + int unpriv_sgio; ++ int ghost_delay; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -28,6 +28,7 @@ + #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_GHOST_DELAY GHOST_DELAY_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -23,6 +23,7 @@ + #include "sysfs.h" + #include "discovery.h" + #include "log_pthread.h" ++#include "propsel.h" + #include + #include + +@@ -334,7 +335,7 @@ static uint16_t build_udev_flags(const s + /* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */ + return (mpp->skip_kpartx == SKIP_KPARTX_ON ? + MPATH_UDEV_NO_KPARTX_FLAG : 0) | +- (mpp->nr_active == 0 ? ++ ((mpp->nr_active == 0 || mpp->ghost_delay_tick > 0)? + MPATH_UDEV_NO_PATHS_FLAG : 0) | + (reload && !mpp->force_udev_reload ? + MPATH_UDEV_RELOAD_FLAG : 0); +@@ -343,8 +344,16 @@ static uint16_t build_udev_flags(const s + extern int + dm_addmap_create (struct multipath *mpp, char * params) { + int ro; +- uint16_t udev_flags = build_udev_flags(mpp, 0); ++ uint16_t udev_flags; + ++ select_ghost_delay(mpp); ++ if (conf->daemon && mpp->ghost_delay > 0 && mpp->nr_active && ++ pathcount(mpp, PATH_GHOST) == mpp->nr_active) ++ mpp->ghost_delay_tick = mpp->ghost_delay; ++ else ++ mpp->ghost_delay = 0; ++ ++ udev_flags = build_udev_flags(mpp, 0); + sysfs_set_max_sectors_kb(mpp, 0); + for (ro = 0; ro <= 1; ro++) { + int err; +@@ -373,7 +382,11 @@ dm_addmap_create (struct multipath *mpp, + extern int + dm_addmap_reload (struct multipath *mpp, char *params, int flush) { + int r = 0; +- uint16_t udev_flags = build_udev_flags(mpp, 1); ++ uint16_t udev_flags; ++ ++ if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP)) ++ mpp->ghost_delay_tick = mpp->ghost_delay = 0; ++ udev_flags = build_udev_flags(mpp, 1); + + sysfs_set_max_sectors_kb(mpp, 1); + if (!mpp->force_readonly) +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -1032,6 +1032,25 @@ def_unpriv_sgio_handler(vector strvec) + return 0; + } + ++static int ++def_ghost_delay_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->ghost_delay = GHOST_DELAY_OFF; ++ if ((conf->ghost_delay = atoi(buff)) < 0) ++ conf->ghost_delay = DEFAULT_GHOST_DELAY; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -1895,6 +1914,29 @@ hw_unpriv_sgio_handler(vector strvec) + return 0; + } + ++static int ++hw_ghost_delay_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->ghost_delay = GHOST_DELAY_OFF; ++ if ((hwe->ghost_delay = atoi(buff)) < 0) ++ hwe->ghost_delay = DEFAULT_GHOST_DELAY; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * multipaths block handlers + */ +@@ -2474,6 +2516,29 @@ mp_unpriv_sgio_handler(vector strvec) + return 0; + } + ++static int ++mp_ghost_delay_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")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ mpe->ghost_delay = GHOST_DELAY_OFF; ++ if ((mpe->ghost_delay = atoi(buff)) < 0) ++ mpe->ghost_delay = DEFAULT_GHOST_DELAY; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * config file keywords printing + */ +@@ -2788,6 +2853,19 @@ snprint_mp_unpriv_sgio (char * buff, int + } + + static int ++snprint_mp_ghost_delay (char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->ghost_delay == GHOST_DELAY_UNDEF) ++ return 0; ++ else if (mpe->ghost_delay == GHOST_DELAY_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "%d", mpe->ghost_delay); ++} ++ ++static int + snprint_hw_fast_io_fail(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -3202,6 +3280,19 @@ snprint_hw_unpriv_sgio(char * buff, int + } + + static int ++snprint_hw_ghost_delay (char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->ghost_delay == GHOST_DELAY_UNDEF) ++ return 0; ++ else if (hwe->ghost_delay == GHOST_DELAY_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "%d", hwe->ghost_delay); ++} ++ ++static int + snprint_def_polling_interval (char * buff, int len, void * data) + { + return snprintf(buff, len, "%i", conf->checkint); +@@ -3696,6 +3787,16 @@ snprint_def_unpriv_sgio(char * buff, int + } + + static int ++snprint_def_ghost_delay (char * buff, int len, void * data) ++{ ++ if (conf->ghost_delay == GHOST_DELAY_OFF || ++ conf->ghost_delay == GHOST_DELAY_UNDEF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "%d", conf->ghost_delay); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3792,6 +3893,7 @@ init_keywords(void) + 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); ++ install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay); + __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); +@@ -3863,6 +3965,7 @@ init_keywords(void) + 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_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay); + install_sublevel_end(); + + install_keyword_root("overrides", &nop_handler); +@@ -3923,5 +4026,6 @@ init_keywords(void) + 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_keyword("ghost_delay", &mp_ghost_delay_handler, &snprint_mp_ghost_delay); + install_sublevel_end(); + } +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -966,3 +966,29 @@ select_unpriv_sgio (struct multipath * m + condlog(3, "unpriv_sgio = DISABLED (internal default)"); + return 0; + } ++ ++extern int ++select_ghost_delay (struct multipath * mp) ++{ ++ if (mp->mpe && mp->mpe->ghost_delay != GHOST_DELAY_UNDEF) { ++ mp->ghost_delay = mp->mpe->ghost_delay; ++ condlog(3, "ghost_delay = %i (multipath setting)", ++ mp->ghost_delay); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->ghost_delay != GHOST_DELAY_UNDEF) { ++ mp->ghost_delay = mp->hwe->ghost_delay; ++ condlog(3, "ghost_delay = %i (controler setting)", ++ mp->ghost_delay); ++ return 0; ++ } ++ if (conf->ghost_delay != GHOST_DELAY_UNDEF) { ++ mp->ghost_delay = conf->ghost_delay; ++ condlog(3, "ghost_delay = %i (config file default)", ++ mp->ghost_delay); ++ return 0; ++ } ++ mp->ghost_delay = DEFAULT_GHOST_DELAY; ++ condlog(3, "ghost_delay = DISABLED (internal default)"); ++ return 0; ++} +Index: multipath-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/libmultipath/propsel.h +@@ -27,3 +27,4 @@ int select_delay_wait_checks (struct mul + int select_skip_kpartx (struct multipath * mp); + int select_max_sectors_kb (struct multipath * mp); + int select_unpriv_sgio (struct multipath * mp); ++int select_ghost_delay (struct multipath * mp); +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -176,6 +176,11 @@ enum prkey_sources { + PRKEY_SOURCE_FILE, + }; + ++enum ghost_delay_states { ++ GHOST_DELAY_OFF = -1, ++ GHOST_DELAY_UNDEF = 0, ++}; ++ + struct sg_id { + int host_no; + int channel; +@@ -273,6 +278,8 @@ struct multipath { + int max_sectors_kb; + int force_readonly; + int unpriv_sgio; ++ int ghost_delay; ++ int ghost_delay_tick; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -195,6 +195,8 @@ sync_map_state(struct multipath *mpp) + pp->state == PATH_WILD || + pp->state == PATH_DELAYED) + continue; ++ if (mpp->ghost_delay_tick > 0) ++ continue; + if ((pp->dmstate == PSTATE_FAILED || + pp->dmstate == PSTATE_UNDEF) && + (pp->state == PATH_UP || pp->state == PATH_GHOST)) +@@ -535,7 +537,7 @@ ev_add_path (struct path * pp, struct ve + if (mpp && mpp->wait_for_udev) { + if (pathcount(mpp, PATH_UP) == 0 && + (pathcount(mpp, PATH_GHOST) == 0 || +- pp->tpgs == TPGS_IMPLICIT)) ++ mpp->ghost_delay_tick > 0 || pp->tpgs == TPGS_IMPLICIT)) + mpp->force_udev_reload = 1; + else { + condlog(2, "%s [%s]: delaying path addition until %s is fully initialized", pp->dev, pp->dev_t, mpp->alias); +@@ -1215,6 +1217,28 @@ missing_uev_wait_tick(struct vectors *ve + } + + static void ++ghost_delay_tick(struct vectors *vecs) ++{ ++ struct multipath * mpp; ++ unsigned int i; ++ ++ vector_foreach_slot (vecs->mpvec, mpp, i) { ++ if (mpp->ghost_delay_tick <= 0) ++ continue; ++ if (--mpp->ghost_delay_tick <= 0) { ++ condlog(0, "%s: timed out waiting for active path", ++ mpp->alias); ++ if (update_map(mpp, vecs) != 0) { ++ /* update_map removed map */ ++ i--; ++ continue; ++ } ++ mpp->ghost_delay = mpp->ghost_delay_tick = 0; ++ } ++ } ++} ++ ++static void + defered_failback_tick (vector mpvec) + { + struct multipath * mpp; +@@ -1560,6 +1584,7 @@ checkerloop (void *ap) + defered_failback_tick(vecs->mpvec); + retry_count_tick(vecs->mpvec); + missing_uev_wait_tick(vecs); ++ ghost_delay_tick(vecs); + } + if (count) + count--; +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -55,6 +55,7 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO= + ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPATH_NEED_KPARTX}="1" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" ++ENV{DM_NOSCAN}=="1", GOTO="end_mpath" + ENV{DM_ACTIVATION}!="1", ENV{DM_MULTIPATH_NEED_KPARTX}!="1", GOTO="end_mpath" + RUN+="$env{MPATH_SBIN_PATH}/kpartx -an $tempnode", \ + ENV{DM_MULTIPATH_NEED_KPARTX}="" +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -601,6 +601,15 @@ device to the specified value. Default i + 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 ++.TP ++.B ghost_delay ++Sets the number of seconds that multipath will wait after creating a device ++with only ghost paths before marking it ready for use in systemd. This gives ++the active paths time to appear before the multipath runs the hardware handler ++to switch the ghost paths to active ones. Setting this to \fI0\fR or \fIoff\fR ++makes multipath immediately mark a device with only ghost paths as ready. The ++default is ++.I off + . + .SH "blacklist section" + The +@@ -716,6 +725,8 @@ section: + .B max_sectors_kb + .TP + .B unpriv_sgio ++.TP ++.B ghost_delay + .RE + .PD + .LP +@@ -820,6 +831,8 @@ section: + .B max_sectors_kb + .TP + .B unpriv_sgio ++.TP ++.B ghost_delay + .RE + .PD + .LP diff --git a/SOURCES/0232-RHBZ-1456955-property-blacklist.patch b/SOURCES/0232-RHBZ-1456955-property-blacklist.patch new file mode 100644 index 0000000..bebaa4e --- /dev/null +++ b/SOURCES/0232-RHBZ-1456955-property-blacklist.patch @@ -0,0 +1,501 @@ +--- + libmultipath/blacklist.c | 79 +++++++++++++++++++++++++++++++++++++++++---- + libmultipath/blacklist.h | 5 ++ + libmultipath/config.c | 20 ++++++++++- + libmultipath/config.h | 2 + + libmultipath/configure.c | 8 ++++ + libmultipath/dict.c | 38 ++++++++++++++++++++- + libmultipath/discovery.c | 2 + + libmultipath/print.c | 31 +++++++++++++++++ + multipath/multipath.conf.5 | 27 ++++++++++++++- + 9 files changed, 200 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/blacklist.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.c ++++ multipath-tools-130222/libmultipath/blacklist.c +@@ -2,6 +2,7 @@ + * Copyright (c) 2004, 2005 Christophe Varoqui + */ + #include ++#include + + #include "checkers.h" + #include "memory.h" +@@ -102,7 +103,7 @@ set_ble_device (vector blist, char * ven + } + + int +-_blacklist_exceptions (vector elist, char * str) ++_blacklist_exceptions (vector elist, const char * str) + { + int i; + struct blentry * ele; +@@ -115,7 +116,7 @@ _blacklist_exceptions (vector elist, cha + } + + int +-_blacklist (vector blist, char * str) ++_blacklist (vector blist, const char * str) + { + int i; + struct blentry * ble; +@@ -208,11 +209,14 @@ setup_default_blist (struct config * con + condlog(3, "%s: (%s:%s) %s", dev, vendor, product, (M)); \ + else if (wwid) \ + condlog(3, "%s: (%s) %s", dev, wwid, (M)); \ ++ else if (env) \ ++ condlog(3, "%s: (%s) %s", dev, env, (M)); \ + else \ + condlog(3, "%s: %s", dev, (M)) + + void +-log_filter (char *dev, char *vendor, char *product, char *wwid, int r) ++log_filter (const char *dev, char *vendor, char *product, char *wwid, ++ const char *env, int r) + { + /* + * Try to sort from most likely to least. +@@ -229,6 +233,9 @@ log_filter (char *dev, char *vendor, cha + case MATCH_DEVNODE_BLIST: + LOG_BLIST("device node name blacklisted"); + break; ++ case MATCH_PROPERTY_BLIST: ++ LOG_BLIST("udev property blacklisted"); ++ break; + case MATCH_DEVICE_BLIST_EXCEPT: + LOG_BLIST("vendor/product whitelisted"); + break; +@@ -238,6 +245,12 @@ log_filter (char *dev, char *vendor, cha + case MATCH_DEVNODE_BLIST_EXCEPT: + LOG_BLIST("device node name whitelisted"); + break; ++ case MATCH_PROPERTY_BLIST_EXCEPT: ++ LOG_BLIST("udev property whitelisted"); ++ break; ++ case MATCH_PROPERTY_BLIST_MISSING: ++ LOG_BLIST("blacklisted, udev property missing"); ++ break; + } + } + +@@ -257,7 +270,7 @@ int + filter_device (vector blist, vector elist, char * vendor, char * product) + { + int r = _filter_device(blist, elist, vendor, product); +- log_filter(NULL, vendor, product, NULL, r); ++ log_filter(NULL, vendor, product, NULL, NULL, r); + return r; + } + +@@ -277,7 +290,7 @@ int + filter_devnode (vector blist, vector elist, char * dev) + { + int r = _filter_devnode(blist, elist, dev); +- log_filter(dev, NULL, NULL, NULL, r); ++ log_filter(dev, NULL, NULL, NULL, NULL, r); + return r; + } + +@@ -297,15 +310,67 @@ int + filter_wwid (vector blist, vector elist, char * wwid) + { + int r = _filter_wwid(blist, elist, wwid); +- log_filter(NULL, NULL, NULL, wwid, r); ++ log_filter(NULL, NULL, NULL, wwid, NULL, r); + return r; + } + + int ++_filter_property (struct config *conf, const char *env) ++{ ++ if (_blacklist_exceptions(conf->elist_property, env)) ++ return MATCH_PROPERTY_BLIST_EXCEPT; ++ if (_blacklist(conf->blist_property, env)) ++ return MATCH_PROPERTY_BLIST; ++ ++ return 0; ++} ++ ++int ++filter_property(struct config * conf, struct udev_device * udev) ++{ ++ const char *devname = udev_device_get_sysname(udev); ++ struct udev_list_entry *list_entry; ++ int r; ++ ++ if (!udev || (!VECTOR_SIZE(conf->elist_property) && ++ !VECTOR_SIZE(conf->blist_property))) ++ return 0; ++ ++ udev_list_entry_foreach(list_entry, ++ udev_device_get_properties_list_entry(udev)) { ++ const char *env; ++ ++ env = udev_list_entry_get_name(list_entry); ++ if (!env) ++ continue; ++ ++ r = _filter_property(conf, env); ++ if (r) { ++ log_filter(devname, NULL, NULL, NULL, env, r); ++ return r; ++ } ++ } ++ ++ /* ++ * This is the inverse of the 'normal' matching; ++ * the environment variable _has_ to match. ++ */ ++ if (VECTOR_SIZE(conf->elist_property)) { ++ log_filter(devname, NULL, NULL, NULL, NULL, ++ MATCH_PROPERTY_BLIST_MISSING); ++ return MATCH_PROPERTY_BLIST_MISSING; ++ } ++ return 0; ++} ++ ++int + _filter_path (struct config * conf, struct path * pp) + { + int r; + ++ r = filter_property(conf, pp->udev); ++ if (r > 0) ++ return r; + r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev); + if (r > 0) + return r; +@@ -321,7 +386,7 @@ int + filter_path (struct config * conf, struct path * pp) + { + int r=_filter_path(conf, pp); +- log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, r); ++ log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, r); + return r; + } + +Index: multipath-tools-130222/libmultipath/blacklist.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.h ++++ multipath-tools-130222/libmultipath/blacklist.h +@@ -1,15 +1,19 @@ + #ifndef _BLACKLIST_H + #define _BLACKLIST_H + ++#include + #include "regex.h" + + #define MATCH_NOTHING 0 + #define MATCH_WWID_BLIST 1 + #define MATCH_DEVICE_BLIST 2 + #define MATCH_DEVNODE_BLIST 3 ++#define MATCH_PROPERTY_BLIST 4 ++#define MATCH_PROPERTY_BLIST_MISSING 5 + #define MATCH_WWID_BLIST_EXCEPT -MATCH_WWID_BLIST + #define MATCH_DEVICE_BLIST_EXCEPT -MATCH_DEVICE_BLIST + #define MATCH_DEVNODE_BLIST_EXCEPT -MATCH_DEVNODE_BLIST ++#define MATCH_PROPERTY_BLIST_EXCEPT -MATCH_PROPERTY_BLIST + + struct blentry { + char * str; +@@ -31,6 +35,7 @@ int filter_devnode (vector, vector, char + int filter_wwid (vector, vector, char *); + int filter_device (vector, vector, char *, char *); + int filter_path (struct config *, struct path *); ++int filter_property(struct config *, struct udev_device *); + int store_ble (vector, char *, int); + int set_ble_device (vector, char *, char *, int); + void free_blacklist (vector); +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -597,10 +597,12 @@ free_config (struct config * conf) + + free_blacklist(conf->blist_devnode); + free_blacklist(conf->blist_wwid); ++ free_blacklist(conf->blist_property); + free_blacklist_device(conf->blist_device); + + free_blacklist(conf->elist_devnode); + free_blacklist(conf->elist_wwid); ++ free_blacklist(conf->elist_property); + free_blacklist_device(conf->elist_device); + + free_mptable(conf->mptable); +@@ -779,8 +781,12 @@ load_config (char * file, struct udev *u + if (!conf->blist_device) + goto out; + } +- if (setup_default_blist(conf)) +- goto out; ++ if (conf->blist_property == NULL) { ++ conf->blist_property = vector_alloc(); ++ ++ if (!conf->blist_property) ++ goto out; ++ } + + if (conf->elist_devnode == NULL) { + conf->elist_devnode = vector_alloc(); +@@ -802,6 +808,16 @@ load_config (char * file, struct udev *u + goto out; + } + ++ if (conf->elist_property == NULL) { ++ conf->elist_property = vector_alloc(); ++ ++ if (!conf->elist_property) ++ goto out; ++ } ++ ++ if (setup_default_blist(conf)) ++ goto out; ++ + if (conf->mptable == NULL) { + conf->mptable = vector_alloc(); + if (!conf->mptable) +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -189,9 +189,11 @@ struct config { + vector blist_devnode; + vector blist_wwid; + vector blist_device; ++ vector blist_property; + vector elist_devnode; + vector elist_wwid; + vector elist_device; ++ vector elist_property; + }; + + struct config * conf; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -1027,6 +1027,10 @@ get_refwwid (char * dev, enum devtypes d + return ret; + } + } ++ if (pp->udev && pp->uid_attribute && ++ filter_property(conf, pp->udev) > 0) ++ return 2; ++ + refwwid = pp->wwid; + goto out; + } +@@ -1051,6 +1055,10 @@ get_refwwid (char * dev, enum devtypes d + return ret; + } + } ++ if (pp->udev && pp->uid_attribute && ++ filter_property(conf, pp->udev) > 0) ++ return 2; ++ + refwwid = pp->wwid; + goto out; + } +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -1063,8 +1063,11 @@ blacklist_handler(vector strvec) + conf->blist_wwid = vector_alloc(); + if (!conf->blist_device) + conf->blist_device = vector_alloc(); ++ if (!conf->blist_property) ++ conf->blist_property = vector_alloc(); + +- if (!conf->blist_devnode || !conf->blist_wwid || !conf->blist_device) ++ if (!conf->blist_devnode || !conf->blist_wwid || ++ !conf->blist_device || !conf->blist_property) + return 1; + + return 0; +@@ -1079,8 +1082,11 @@ blacklist_exceptions_handler(vector strv + conf->elist_wwid = vector_alloc(); + if (!conf->elist_device) + conf->elist_device = vector_alloc(); ++ if (!conf->elist_property) ++ conf->elist_property = vector_alloc(); + +- if (!conf->elist_devnode || !conf->elist_wwid || !conf->elist_device) ++ if (!conf->elist_devnode || !conf->elist_wwid || ++ !conf->elist_device || !conf->elist_property) + return 1; + + return 0; +@@ -1139,6 +1145,32 @@ ble_except_wwid_handler(vector strvec) + } + + static int ++ble_property_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ return store_ble(conf->blist_property, buff, ORIGIN_CONFIG); ++} ++ ++static int ++ble_except_property_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ return store_ble(conf->elist_property, buff, ORIGIN_CONFIG); ++} ++ ++static int + ble_device_handler(vector strvec) + { + return alloc_ble_device(conf->blist_device); +@@ -3903,6 +3935,7 @@ init_keywords(void) + install_keyword_root("blacklist", &blacklist_handler); + install_keyword_multi("devnode", &ble_devnode_handler, &snprint_ble_simple); + install_keyword_multi("wwid", &ble_wwid_handler, &snprint_ble_simple); ++ install_keyword_multi("property", &ble_property_handler, &snprint_ble_simple); + install_keyword_multi("device", &ble_device_handler, NULL); + install_sublevel(); + install_keyword("vendor", &ble_vendor_handler, &snprint_bled_vendor); +@@ -3911,6 +3944,7 @@ init_keywords(void) + install_keyword_root("blacklist_exceptions", &blacklist_exceptions_handler); + install_keyword_multi("devnode", &ble_except_devnode_handler, &snprint_ble_simple); + install_keyword_multi("wwid", &ble_except_wwid_handler, &snprint_ble_simple); ++ install_keyword_multi("property", &ble_except_property_handler, &snprint_ble_simple); + install_keyword_multi("device", &ble_except_device_handler, NULL); + install_sublevel(); + install_keyword("vendor", &ble_except_vendor_handler, &snprint_bled_vendor); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1332,6 +1332,8 @@ pathinfo (struct path *pp, vector hwtabl + * limited by DI_BLACKLIST and occurs before this debug + * message with the mask value. + */ ++ if (pp->udev && filter_property(conf, pp->udev) > 0) ++ return PATHINFO_SKIPPED; + if (filter_devnode(conf->blist_devnode, + conf->elist_devnode, + pp->dev) > 0) +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -1415,6 +1415,19 @@ snprint_blacklist_report (char * buff, i + + if ((len - fwd - threshold) <= 0) + return len; ++ fwd += snprintf(buff + fwd, len - fwd, "udev property rules:\n" ++ "- blacklist:\n"); ++ if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_property)) ++ return len; ++ ++ if ((len - fwd - threshold) <= 0) ++ return len; ++ fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n"); ++ if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_property) == 0) ++ return len; ++ ++ if ((len - fwd - threshold) <= 0) ++ return len; + fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n" + "- blacklist:\n"); + if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0) +@@ -1480,6 +1493,15 @@ snprint_blacklist (char * buff, int len) + if (fwd > len) + return len; + } ++ vector_foreach_slot (conf->blist_property, ble, i) { ++ kw = find_keyword(rootkw->sub, "property"); ++ if (!kw) ++ return 0; ++ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", ++ kw, ble); ++ if (fwd > len) ++ return len; ++ } + rootkw = find_keyword(rootkw->sub, "device"); + if (!rootkw) + return 0; +@@ -1544,6 +1566,15 @@ snprint_blacklist_except (char * buff, i + if (!kw) + return 0; + fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", ++ kw, ele); ++ if (fwd > len) ++ return len; ++ } ++ vector_foreach_slot (conf->elist_property, ele, i) { ++ kw = find_keyword(rootkw->sub, "property"); ++ if (!kw) ++ return 0; ++ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", + kw, ele); + if (fwd > len) + return len; +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -626,6 +626,9 @@ The \fIWorld Wide Identification\fR of a + .B devnode + Regular expression of the device nodes to be excluded. + .TP ++.B property ++Regular expresion of the udev property to be excluded. ++.TP + .B device + Subsection for the device description. This subsection recognizes the + .I vendor +@@ -650,8 +653,11 @@ The following keywords are recognized: + .B wwid + The \fIWorld Wide Identification\fR of a device. + .TP ++.B property ++Regular expresion of the udev property to be whitelisted. ++.TP + .B devnode +-Regular expression of the device nodes to be excluded. ++Regular expression of the device nodes to be whitelisted. + .TP + .B device + Subsection for the device description. This subsection recognizes the +@@ -661,6 +667,25 @@ and + keywords. For a full description of these keywords please see the + .I devices + section description. ++.LP ++The ++.I property ++blacklist and whitelist handling is different from the usual handling ++in the sense that if the whitelist is set, it ++.B has ++to match, otherwise the device will be blacklisted. ++In these cases the message ++.I blacklisted, udev property missing ++will be displayed. For example settting the ++.I property ++blacklist_exception to ++.I (SCSI_IDENT_|ID_WWN) ++will blacklist all devices that have no udev property whose name regex matches ++either ++.I SCSI_IDENT_ ++or ++.I ID_WWN. ++This works to exclude most non-multipathable devices. + .SH "multipaths section" + The only recognized attribute for the + .B multipaths diff --git a/SOURCES/0233-RHBZ-1451852-1482629-nimble-config.patch b/SOURCES/0233-RHBZ-1451852-1482629-nimble-config.patch new file mode 100644 index 0000000..96c9985 --- /dev/null +++ b/SOURCES/0233-RHBZ-1451852-1482629-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/SOURCES/0234-RHBZ-1500109-doc-typo.patch b/SOURCES/0234-RHBZ-1500109-doc-typo.patch new file mode 100644 index 0000000..a9484db --- /dev/null +++ b/SOURCES/0234-RHBZ-1500109-doc-typo.patch @@ -0,0 +1,17 @@ +--- + multipath/multipath.conf.5 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -388,7 +388,7 @@ retry interval + \fIno_path_retry\fR * \fIpolling_interval\fR + if a number of retries is given with \fIno_path_retry\fR and the + overall retry interval is longer than the specified \fIdev_loss_tmo\fR value. +-The linux kernel will cap this value to \fI300\fR if \fBfast_io_fail_tmo\fR ++The linux kernel will cap this value to \fI600\fR if \fBfast_io_fail_tmo\fR + is not set. + .TP + .B queue_without_daemon diff --git a/SOURCES/0235-RHBZ-1480638-NVMe-support.patch b/SOURCES/0235-RHBZ-1480638-NVMe-support.patch new file mode 100644 index 0000000..bf1d580 --- /dev/null +++ b/SOURCES/0235-RHBZ-1480638-NVMe-support.patch @@ -0,0 +1,503 @@ +--- + libmultipath/checkers.c | 19 +++- + libmultipath/checkers.h | 3 + libmultipath/discovery.c | 183 +++++++++++++++++++++++++++++++++++++++------ + libmultipath/discovery.h | 2 + libmultipath/hwtable.c | 10 ++ + libmultipath/structs.h | 1 + libmultipath/uevent.c | 2 + multipath/multipath.conf.5 | 3 + multipathd/main.c | 27 ------ + 9 files changed, 194 insertions(+), 56 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include "checkers.h" + #include "vector.h" +@@ -881,6 +882,46 @@ scsi_sysfs_pathinfo (struct path * pp) + } + + static int ++nvme_sysfs_pathinfo (struct path * pp) ++{ ++ struct udev_device *parent; ++ const char *attr_path = NULL; ++ ++ ++ attr_path = udev_device_get_sysname(pp->udev); ++ if (!attr_path) ++ return 1; ++ ++ if (sscanf(attr_path, "nvme%dn%d", ++ &pp->sg_id.host_no, ++ &pp->sg_id.scsi_id) != 2) ++ return 1; ++ pp->sg_id.channel = 0; ++ pp->sg_id.lun = 0; ++ ++ parent = udev_device_get_parent(pp->udev); ++ if (!parent) ++ return 1; ++ ++ snprintf(pp->vendor_id, SCSI_VENDOR_SIZE, "NVME"); ++ snprintf(pp->product_id, SCSI_PRODUCT_SIZE, "%s", ++ udev_device_get_sysattr_value(parent, "model")); ++ snprintf(pp->serial, SERIAL_SIZE, "%s", ++ udev_device_get_sysattr_value(parent, "serial")); ++ snprintf(pp->rev, SCSI_REV_SIZE, "%s", ++ udev_device_get_sysattr_value(parent, "firmware_rev")); ++ ++ condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id); ++ condlog(3, "%s: product = %s", pp->dev, pp->product_id); ++ condlog(3, "%s: serial = %s", pp->dev, pp->serial); ++ condlog(3, "%s: rev = %s", pp->dev, pp->rev); ++ ++ pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL); ++ ++ return 0; ++} ++ ++static int + rbd_sysfs_pathinfo (struct path * pp) + { + sprintf(pp->vendor_id, "Ceph"); +@@ -1040,14 +1081,20 @@ path_offline (struct path * pp) + { + struct udev_device * parent; + char buff[SCSI_STATE_SIZE]; ++ const char *subsys_type; + +- if (pp->bus != SYSFS_BUS_SCSI) ++ if (pp->bus == SYSFS_BUS_SCSI) ++ subsys_type = "scsi"; ++ else if (pp->bus == SYSFS_BUS_NVME) ++ subsys_type = "nvme"; ++ else + return PATH_UP; + + parent = pp->udev; + while (parent) { + const char *subsys = udev_device_get_subsystem(parent); +- if (subsys && !strncmp(subsys, "scsi", 4)) ++ if (subsys && !strncmp(subsys, subsys_type, ++ strlen(subsys_type))) + break; + parent = udev_device_get_parent(parent); + } +@@ -1063,15 +1110,30 @@ path_offline (struct path * pp) + + condlog(3, "%s: path state = %s", pp->dev, buff); + +- if (!strncmp(buff, "offline", 7)) { +- pp->offline = 1; +- return PATH_DOWN; ++ if (pp->bus == SYSFS_BUS_SCSI) { ++ if (!strncmp(buff, "offline", 7)) { ++ pp->offline = 1; ++ return PATH_DOWN; ++ } ++ pp->offline = 0; ++ if (!strncmp(buff, "blocked", 7) || ++ !strncmp(buff, "quiesce", 7)) ++ return PATH_PENDING; ++ else if (!strncmp(buff, "running", 7)) ++ return PATH_UP; ++ } ++ else if (pp->bus == SYSFS_BUS_NVME) { ++ if (!strncmp(buff, "dead", 4)) { ++ pp->offline = 1; ++ return PATH_DOWN; ++ } ++ pp->offline = 0; ++ if (!strncmp(buff, "new", 3) || ++ !strncmp(buff, "deleting", 8)) ++ return PATH_PENDING; ++ else if (!strncmp(buff, "live", 4)) ++ return PATH_UP; + } +- pp->offline = 0; +- if (!strncmp(buff, "blocked", 7) || !strncmp(buff, "quiesce", 7)) +- return PATH_PENDING; +- else if (!strncmp(buff, "running", 7)) +- return PATH_UP; + + return PATH_DOWN; + } +@@ -1091,6 +1153,8 @@ sysfs_pathinfo(struct path * pp) + pp->bus = SYSFS_BUS_SCSI; + if (!strncmp(pp->dev,"rbd", 3)) + pp->bus = SYSFS_BUS_RBD; ++ if (!strncmp(pp->dev,"nvme", 4)) ++ pp->bus = SYSFS_BUS_NVME; + + if (pp->bus == SYSFS_BUS_UNDEF) + return 0; +@@ -1106,6 +1170,9 @@ sysfs_pathinfo(struct path * pp) + } else if (pp->bus == SYSFS_BUS_RBD) { + if (rbd_sysfs_pathinfo(pp)) + return 1; ++ } else if (pp->bus == SYSFS_BUS_NVME) { ++ if (nvme_sysfs_pathinfo(pp)) ++ return 1; + } + return 0; + } +@@ -1132,7 +1199,7 @@ cciss_ioctl_pathinfo (struct path * pp, + } + + int +-get_state (struct path * pp, int daemon) ++get_state (struct path * pp, int daemon, int oldstate) + { + struct checker * c = &pp->checker; + int state; +@@ -1171,8 +1238,9 @@ get_state (struct path * pp, int daemon) + (pp->bus != SYSFS_BUS_SCSI || + sysfs_get_timeout(pp, &(c->timeout)))) + c->timeout = DEF_TIMEOUT; +- state = checker_check(c); +- condlog(3, "%s: state = %s", pp->dev, checker_state_name(state)); ++ state = checker_check(c, oldstate); ++ condlog(3, "%s: %s state = %s", pp->dev, ++ checker_name(c), checker_state_name(state)); + if (state != PATH_UP && state != PATH_GHOST && + strlen(checker_message(c))) + condlog(3, "%s: checker msg is \"%s\"", +@@ -1256,6 +1324,82 @@ free_dev: + return ret; + } + ++/* ++ * Mangle string of length *len starting at start ++ * by removing character sequence "00" (hex for a 0 byte), ++ * starting at end, backwards. ++ * Changes the value of *len if characters were removed. ++ * Returns a pointer to the position where "end" was moved to. ++ */ ++static char * ++skip_zeroes_backward(char* start, int *len, char *end) ++{ ++ char *p = end; ++ ++ while (p >= start + 2 && *(p - 1) == '0' && *(p - 2) == '0') ++ p -= 2; ++ ++ if (p == end) ++ return p; ++ ++ memmove(p, end, start + *len + 1 - end); ++ *len -= end - p; ++ ++ return p; ++} ++ ++/* ++ * Fix for NVME wwids looking like this: ++ * nvme.0000-3163653363666438366239656630386200-4c696e75780000000000000000000000000000000000000000000000000000000000000000000000-00000002 ++ * which are encountered in some combinations of Linux NVME host and target. ++ * The '00' are hex-encoded 0-bytes which are forbidden in the serial (SN) ++ * and model (MN) fields. Discard them. ++ * If a WWID of the above type is found, sets pp->wwid and returns a value > 0. ++ * Otherwise, returns 0. ++ */ ++static int ++fix_broken_nvme_wwid(struct path *pp, const char *value, int size) ++{ ++ static const char _nvme[] = "nvme."; ++ int len, i; ++ char mangled[256]; ++ char *p; ++ ++ len = strlen(value); ++ if (len >= sizeof(mangled)) ++ return 0; ++ ++ /* Check that value starts with "nvme.%04x-" */ ++ if (memcmp(value, _nvme, sizeof(_nvme) - 1) || value[9] != '-') ++ return 0; ++ for (i = 5; i < 9; i++) ++ if (!isxdigit(value[i])) ++ return 0; ++ ++ memcpy(mangled, value, len + 1); ++ ++ /* search end of "model" part and strip trailing '00' */ ++ p = memrchr(mangled, '-', len); ++ if (p == NULL) ++ return 0; ++ ++ p = skip_zeroes_backward(mangled, &len, p); ++ ++ /* search end of "serial" part */ ++ p = memrchr(mangled, '-', p - mangled); ++ if (p == NULL || memrchr(mangled, '-', p - mangled) != mangled + 9) ++ /* We expect exactly 3 '-' in the value */ ++ return 0; ++ ++ p = skip_zeroes_backward(mangled, &len, p); ++ if (len >= size) ++ return 0; ++ ++ memcpy(pp->wwid, mangled, len + 1); ++ condlog(2, "%s: over-long WWID shortened to %s", pp->dev, pp->wwid); ++ return len; ++} ++ + int + get_uid (struct path * pp, struct udev_device *udev) + { +@@ -1287,14 +1431,10 @@ get_uid (struct path * pp, struct udev_d + conf->cmd == CMD_VALID_PATH) + value = getenv(pp->uid_attribute); + if (value && strlen(value)) { +- size_t len = WWID_SIZE; +- +- if (strlen(value) + 1 > WWID_SIZE) { ++ size_t len = strlcpy(pp->wwid, value, WWID_SIZE); ++ if (len > WWID_SIZE && ++ !fix_broken_nvme_wwid(pp, value, WWID_SIZE)) + condlog(0, "%s: wwid overflow", pp->dev); +- } else { +- len = strlen(value); +- } +- strncpy(pp->wwid, value, len); + condlog(4, "%s: got wwid of '%s'", pp->dev, pp->wwid); + pp->missing_udev_info = INFO_OK; + pp->tick = 0; +@@ -1381,7 +1521,8 @@ pathinfo (struct path *pp, vector hwtabl + + if (mask & DI_CHECKER) { + if (path_state == PATH_UP) { +- pp->chkrstate = pp->state = get_state(pp, 0); ++ pp->chkrstate = pp->state = get_state(pp, 0, ++ path_state); + if (pp->state == PATH_UNCHECKED || + pp->state == PATH_WILD) + goto blank; +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1185,7 +1185,15 @@ static struct hwentry default_hw[] = { + .checker_name = RBD, + .deferred_remove = DEFERRED_REMOVE_ON, + }, +- ++ /* ++ * Generic NVMe devices ++ */ ++ { ++ .vendor = "NVME", ++ .product = ".*", ++ .uid_attribute = "ID_WWN", ++ .checker_name = NONE, ++ }, + /* + * EOL + */ +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -54,6 +54,7 @@ enum sysfs_buses { + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, + SYSFS_BUS_RBD, ++ SYSFS_BUS_NVME, + }; + + enum pathstates { +Index: multipath-tools-130222/libmultipath/checkers.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.c ++++ multipath-tools-130222/libmultipath/checkers.c +@@ -101,6 +101,8 @@ struct checker * add_checker (char * nam + if (!c) + return NULL; + snprintf(c->name, CHECKER_NAME_LEN, "%s", name); ++ if (!strncmp(c->name, NONE, 4)) ++ goto done; + snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so", + conf->multipath_dir, name); + if (stat(libname,&stbuf) < 0) { +@@ -144,7 +146,7 @@ struct checker * add_checker (char * nam + condlog(0, "A dynamic linking error occurred: (%s)", errstr); + if (!c->repair) + goto out; +- ++done: + c->fd = 0; + c->sync = 1; + list_add(&c->node, &checkers); +@@ -194,14 +196,16 @@ int checker_init (struct checker * c, vo + if (!c) + return 1; + c->mpcontext = mpctxt_addr; +- return c->init(c); ++ if (c->init) ++ return c->init(c); ++ return 0; + } + + void checker_put (struct checker * dst) + { + struct checker * src; + +- if (!dst) ++ if (!dst || !strlen(dst->name)) + return; + src = checker_lookup(dst->name); + if (dst->free) +@@ -221,10 +225,11 @@ void checker_repair (struct checker * c) + return; + } + +- c->repair(c); ++ if (c->repair) ++ c->repair(c); + } + +-int checker_check (struct checker * c) ++int checker_check (struct checker * c, int path_state) + { + int r; + +@@ -236,6 +241,8 @@ int checker_check (struct checker * c) + MSG(c, "checker disabled"); + return PATH_UNCHECKED; + } ++ if (!strncmp(c->name, NONE, 4)) ++ return path_state; + if (c->fd <= 0) { + MSG(c, "no usable fd"); + return PATH_WILD; +@@ -249,6 +256,8 @@ int checker_selected (struct checker * c + { + if (!c) + return 0; ++ if (!strncmp(c->name, NONE, 4)) ++ return 1; + return (c->check) ? 1 : 0; + } + +Index: multipath-tools-130222/libmultipath/checkers.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.h ++++ multipath-tools-130222/libmultipath/checkers.h +@@ -75,6 +75,7 @@ enum path_check_state { + #define EMC_CLARIION "emc_clariion" + #define READSECTOR0 "readsector0" + #define CCISS_TUR "cciss_tur" ++#define NONE "none" + #define RBD "rbd" + + #define DEFAULT_CHECKER DIRECTIO +@@ -129,7 +130,7 @@ void checker_set_fd (struct checker *, i + void checker_enable (struct checker *); + void checker_disable (struct checker *); + void checker_repair (struct checker *); +-int checker_check (struct checker *); ++int checker_check (struct checker *, int); + int checker_selected (struct checker *); + char * checker_name (struct checker *); + char * checker_message (struct checker *); +Index: multipath-tools-130222/libmultipath/discovery.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.h ++++ multipath-tools-130222/libmultipath/discovery.h +@@ -35,7 +35,7 @@ int path_discovery (vector pathvec, stru + + int do_tur (char *); + int path_offline (struct path *); +-int get_state (struct path * pp, int daemon); ++int get_state (struct path * pp, int daemon, int state); + int pathinfo (struct path *, vector hwtable, int mask); + int store_pathinfo (vector pathvec, vector hwtable, + struct udev_device *udevice, int flag, +Index: multipath-tools-130222/libmultipath/uevent.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.c ++++ multipath-tools-130222/libmultipath/uevent.c +@@ -447,7 +447,7 @@ int uevent_listen(struct udev *udev) + goto out; + } + err = udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", +- NULL); ++ "disk"); + if (err) + condlog(2, "failed to create filter : %s", strerror(-err)); + err = udev_monitor_enable_receiving(monitor); +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -284,6 +284,9 @@ Check the path state for LSI/Engenio/Net + .B directio + Read the first sector with direct I/O. + .TP ++.B none ++Do not check the device, fallback to use the values retrieved from sysfs ++.TP + .B rbd + Check if the path is in the Ceph blacklist. + .TP +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -908,28 +908,6 @@ out: + return r; + } + +-static int +-uev_discard(char * devpath) +-{ +- char *tmp; +- char a[11], b[11]; +- +- /* +- * keep only block devices, discard partitions +- */ +- tmp = strstr(devpath, "/block/"); +- if (tmp == NULL){ +- condlog(4, "no /block/ in '%s'", devpath); +- return 1; +- } +- if (sscanf(tmp, "/block/%10s", a) != 1 || +- sscanf(tmp, "/block/%10[^/]/%10s", a, b) == 2) { +- condlog(4, "discard event on %s", devpath); +- return 1; +- } +- return 0; +-} +- + int + uev_trigger (struct uevent * uev, void * trigger_data) + { +@@ -938,9 +916,6 @@ uev_trigger (struct uevent * uev, void * + + vecs = (struct vectors *)trigger_data; + +- if (uev_discard(uev->devpath)) +- return 0; +- + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); + pthread_testcancel(); +@@ -1358,7 +1333,7 @@ check_path (struct vectors * vecs, struc + + newstate = path_offline(pp); + if (newstate == PATH_UP) +- newstate = get_state(pp, 1); ++ newstate = get_state(pp, 1, newstate); + else + checker_clear_message(&pp->checker); + diff --git a/SOURCES/0236-RHBZ-1525348-fix-msg.patch b/SOURCES/0236-RHBZ-1525348-fix-msg.patch new file mode 100644 index 0000000..04f9fe7 --- /dev/null +++ b/SOURCES/0236-RHBZ-1525348-fix-msg.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -471,7 +471,7 @@ uev_add_path (struct uevent *uev, struct + + pp = find_path_by_dev(vecs->pathvec, uev->kernel); + if (pp) { +- condlog(0, "%s: spurious uevent, path already in pathvec", ++ condlog(2, "%s: spurious uevent, path already in pathvec", + uev->kernel); + if (pp->mpp) + return 0; diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 7443479..79dc7c9 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}.2 +Release: 119%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -224,10 +224,25 @@ 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 +Patch0218: 0218-RHBZ-1459370-add-feature-fix.patch +Patch0219: 0219-RHBZ-1448970-fix-resize.patch +Patch0220: 0220-RHBZ-1448223-fix-kpartx.patch +Patch0221: 0221-RH-harden-files.patch +Patch0222: 0222-RHBZ-1457288-fix-show-maps-json.patch +Patch0223: 0223-RHBZ-1452210-unpriv-sgio.patch +Patch0224: 0224-RHBZ-1452210-prkey.patch +Patch0225: 0225-RH-udevdir.patch +Patch0226: 0226-RH-allow-overrides-section.patch +Patch0227: 0227-RHBZ-1465773-fix-path-delay-msg.patch +Patch0228: 0228-RHBZ-1464634-hauwei-config-update.patch +Patch0229: 0229-RHBZ-1467987-poll-on-udev-monitor.patch +Patch0230: 0230-UP-allow-invalid-creates.patch +Patch0231: 0231-RHBZ-1458852-delay-readying.patch +Patch0232: 0232-RHBZ-1456955-property-blacklist.patch +Patch0233: 0233-RHBZ-1451852-1482629-nimble-config.patch +Patch0234: 0234-RHBZ-1500109-doc-typo.patch +Patch0235: 0235-RHBZ-1480638-NVMe-support.patch +Patch0236: 0236-RHBZ-1525348-fix-msg.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -536,11 +551,25 @@ device-mapper-multipath's libdmmp C API library %patch0219 -p1 %patch0220 -p1 %patch0221 -p1 +%patch0222 -p1 +%patch0223 -p1 +%patch0224 -p1 +%patch0225 -p1 +%patch0226 -p1 +%patch0227 -p1 +%patch0228 -p1 +%patch0229 -p1 +%patch0230 -p1 +%patch0231 -p1 +%patch0232 -p1 +%patch0233 -p1 +%patch0234 -p1 +%patch0235 -p1 +%patch0236 -p1 cp %{SOURCE1} . %build -%define _sbindir /usr/sbin -%define _libdir /usr/%{_lib} +%define _udevdir %{_prefix}/lib/udev/rules.d %define _libmpathdir %{_libdir}/multipath %define _pkgconfdir %{_libdir}/pkgconfig make %{?_smp_mflags} LIB=%{_lib} @@ -581,12 +610,6 @@ fi # section in multipathd.service from multi-user.target to sysinit.target /bin/systemctl --quiet is-enabled multipathd.service >/dev/null 2>&1 && /bin/systemctl reenable multipathd.service ||: -%triggerun -- %{name} < 0.4.9-16 -%{_bindir}/systemd-sysv-convert --save multipathd >/dev/null 2>&1 ||: -bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: -/sbin/chkconfig --del multipathd >/dev/null 2>&1 || : -/bin/systemctl try-restart multipathd.service >/dev/null 2>&1 || : - %triggerpostun -n %{name}-sysvinit -- %{name} < 0.4.9-16 /sbin/chkconfig --add mdmonitor >/dev/null 2>&1 || : @@ -602,8 +625,8 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/multipathd.8.gz %{_mandir}/man8/mpathconf.8.gz %{_mandir}/man8/mpathpersist.8.gz -%config /usr/lib/udev/rules.d/62-multipath.rules -%config /usr/lib/udev/rules.d/11-dm-mpath.rules +%config %{_udevdir}/62-multipath.rules +%config %{_udevdir}/11-dm-mpath.rules %doc AUTHOR COPYING FAQ %doc multipath.conf %dir /etc/multipath @@ -660,22 +683,80 @@ 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 Jan 31 2018 Benjamin Marzinski 0.4.9-119 +- Add 0236-RHBZ-1525348-fix-msg.patch + * reduced message serverity level +- Resolves: bz #1525348 -* Wed Nov 8 2017 Benjamin Marzinski 0.4.9-111.1 -- Add 0218-RHBZ-1510837-add-feature-fix.patch +* Fri Nov 17 2017 Benjamin Marzinski 0.4.9-118 +- Modify 0224-RHBZ-1452210-prkey.patch + * Improve error checking for mpathpersist +- Resolves: bz #1452210 + +* Thu Nov 16 2017 Benjamin Marzinski 0.4.9-117 +- Modify 0235-RHBZ-1480638-NVMe-support.patch + * remove overly-restrictive uevent filtering +- Resolves: bz #1480638 + +* Tue Oct 31 2017 Benjamin Marzinski 0.4.9-116 +- Add 0235-RHBZ-1480638-NVMe-support.patch + * adds support for multipathing NVMe devices +- Resolves: bz #1480638 + +* Tue Oct 10 2017 Benjamin Marzinski 0.4.9-115 +- Add 0233-RHBZ-1451852-1482629-nimble-config.patch +- Add 0234-RHBZ-1500109-doc-typo.patch +- Remove old triggerun scriptlet (bz1470384) +- Resolves: bz #1451852, #1470384, #1482629, #1500109 + +* Tue Oct 3 2017 Benjamin Marzinski 0.4.9-114 +- Add 0226-RH-allow-overrides-section.patch + * This is a dummy section that exists to help the transition to RHEL8 +- Add 0227-RHBZ-1465773-fix-path-delay-msg.patch +- Add 0228-RHBZ-1464634-hauwei-config-update.patch +- Add 0229-RHBZ-1467987-poll-on-udev-monitor.patch + * Do poll first, so udev_monitor_receive_device doesn't return error when + there is no uevent +- Add 0230-UP-allow-invalid-creates.patch + * Allow creation of devices with no valid paths. +- Add 0231-RHBZ-1458852-delay-readying.patch + * Add ghost_delay configuration option to delay device activation when only + ghost paths exist. +- Add 0232-RHBZ-1456955-property-blacklist.patch + * Add the "property" blacklist type. +- Resolves: bz #1456955, #1458852, #1464634, #1465773, #1467987 + +* Wed Sep 20 2017 Benjamin Marzinski 0.4.9-113 +- Modify 0224-RHBZ-1452210-prkey.patch + * fix errow with telling multipathd to set prkeys +- Add 0225-RH-udevdir.patch + * fix rpmdiff complaint about udev rules installation +- Resolves: bz #1452210 + +* Tue Sep 19 2017 Benjamin Marzinski 0.4.9-112 +- Modify 0191-RHBZ-1169168-disable-changed-paths.patch + * man page fixup +- Modfiy 0197-RHBZ-1394059-max-sectors-kb.patch + * man page fixup +- Modify 0205-RHBZ-1416569-reset-stats.patch + * man page fixup +- Add 0218-RHBZ-1459370-add-feature-fix.patch * handle null feature string -- Add 0219-RHBZ-1510834-unpriv-sgio.patch +- Add 0219-RHBZ-1448970-fix-resize.patch + * if the resize fails, try to resume again with the old table. +- Add 0220-RHBZ-1448223-fix-kpartx.patch + * gracefully fail when run on something other than a file or block device +- Add 0221-RH-harden-files.patch + * change build parameters to use position independent code +- Add 0222-RHBZ-1457288-fix-show-maps-json.patch + * handle running "show maps json" with no multipath devices present +- Add 0223-RHBZ-1452210-unpriv-sgio.patch * add unpriv_sgio configuration option to set unpriv_sgio on multipath device and paths -- Add 0220-RHBZ-1510834-prkey.patch +- Add 0224-RHBZ-1452210-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 +- Resolves: bz #1459370, #1448970, #1448223, #1457288, #1452210 * Mon May 15 2017 Benjamin Marzinski 0.4.9-111 - Remove 0217-RHBZ-1437329-blacklist-oracle-devs.patch