diff --git a/SOURCES/0258-RHBZ-1634183-ANA-prioritizer.patch b/SOURCES/0258-RHBZ-1634183-ANA-prioritizer.patch index 5c87985..8657022 100644 --- a/SOURCES/0258-RHBZ-1634183-ANA-prioritizer.patch +++ b/SOURCES/0258-RHBZ-1634183-ANA-prioritizer.patch @@ -2539,7 +2539,7 @@ Index: multipath-tools-130222/libmultipath/nvme-ioctl.c +static int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12, + bool save, __u32 data_len, void *data, __u32 *result) +{ -+ __u32 cdw10 = fid | (save ? 1 << 31 : 0); ++ __u32 cdw10 = fid | (save ? 0x80000000 : 0); + + return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value, + cdw12, data_len, data, result); diff --git a/SOURCES/0259-RHBZ-1701604-fix-nr-active.patch b/SOURCES/0259-RHBZ-1701604-fix-nr-active.patch new file mode 100644 index 0000000..e6973bb --- /dev/null +++ b/SOURCES/0259-RHBZ-1701604-fix-nr-active.patch @@ -0,0 +1,71 @@ +--- + libmultipath/structs_vec.c | 24 +++++++++++++++++------- + multipathd/main.c | 2 ++ + 2 files changed, 19 insertions(+), 7 deletions(-) + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -312,24 +312,33 @@ update_multipath_strings (struct multipa + extern void + set_no_path_retry(struct multipath *mpp) + { +- mpp->retry_tick = 0; ++ char is_queueing = 0; ++ + mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST); +- select_no_path_retry(mpp); ++ if (mpp->features && strstr(mpp->features, "queue_if_no_path")) ++ is_queueing = 1; + + switch (mpp->no_path_retry) { + case NO_PATH_RETRY_UNDEF: + break; + case NO_PATH_RETRY_FAIL: +- dm_queue_if_no_path(mpp->alias, 0); ++ if (is_queueing) ++ dm_queue_if_no_path(mpp->alias, 0); + break; + case NO_PATH_RETRY_QUEUE: +- dm_queue_if_no_path(mpp->alias, 1); ++ if (!is_queueing) ++ dm_queue_if_no_path(mpp->alias, 1); + break; + default: +- dm_queue_if_no_path(mpp->alias, 1); +- if (mpp->nr_active == 0) { ++ if (mpp->nr_active > 0) { ++ mpp->retry_tick = 0; ++ if (!is_queueing) ++ dm_queue_if_no_path(mpp->alias, 1); ++ } else if (is_queueing && mpp->retry_tick == 0) { + /* Enter retry mode */ +- mpp->retry_tick = mpp->no_path_retry * conf->checkint; ++ mpp->stat_queueing_timeouts++; ++ mpp->retry_tick = mpp->no_path_retry * ++ conf->checkint + 1; + condlog(1, "%s: Entering recovery mode: max_retries=%d", + mpp->alias, mpp->no_path_retry); + } +@@ -360,6 +369,7 @@ __setup_multipath (struct vectors * vecs + if (reset) { + select_rr_weight(mpp); + select_pgfailback(mpp); ++ select_no_path_retry(mpp); + set_no_path_retry(mpp); + select_pg_timeout(mpp); + select_flush_on_last_del(mpp); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1464,6 +1464,8 @@ check_path (struct vectors * vecs, struc + if (!pp->mpp) + return 0; + ++ set_no_path_retry(pp->mpp); ++ + if ((newstate == PATH_UP || newstate == PATH_GHOST) && + pp->io_err_disable_reinstate && need_io_err_check(pp)) { + pp->state = PATH_SHAKY; diff --git a/SOURCES/0260-RHBZ-1634183-prio-fixes.patch b/SOURCES/0260-RHBZ-1634183-prio-fixes.patch new file mode 100644 index 0000000..cddeae0 --- /dev/null +++ b/SOURCES/0260-RHBZ-1634183-prio-fixes.patch @@ -0,0 +1,67 @@ +--- + libmultipath/discovery.c | 15 +++++++++++++-- + libmultipath/pgpolicies.c | 2 +- + libmultipath/prioritizers/ana.c | 2 +- + 3 files changed, 15 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1234,6 +1234,7 @@ get_state (struct path * pp, int daemon, + static int + get_prio (struct path * pp) + { ++ int old_prio; + if (!pp) + return 0; + +@@ -1247,10 +1248,20 @@ get_prio (struct path * pp) + return 1; + } + } ++ old_prio = pp->priority; + pp->priority = prio_getprio(p, pp); + if (pp->priority < 0) { +- condlog(3, "%s: %s prio error", pp->dev, prio_name(p)); +- pp->priority = PRIO_UNDEF; ++ /* this changes pp->offline, but why not */ ++ int state = path_offline(pp); ++ ++ if (state == PATH_DOWN || state == PATH_PENDING) { ++ pp->priority = old_prio; ++ condlog(3, "%s: %s prio error in state %d, keeping prio = %d", pp->dev, prio_name(p), state, pp->priority); ++ } else { ++ condlog(3, "%s: %s prio error in state %d", ++ pp->dev, prio_name(p), state); ++ pp->priority = PRIO_UNDEF; ++ } + return 1; + } + condlog(3, "%s: %s prio = %u", +Index: multipath-tools-130222/libmultipath/pgpolicies.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/pgpolicies.c ++++ multipath-tools-130222/libmultipath/pgpolicies.c +@@ -308,7 +308,7 @@ extern int + group_by_prio (struct multipath * mp) + { + int i; +- unsigned int prio; ++ int prio; + struct path * pp; + struct pathgroup * pgp; + +Index: multipath-tools-130222/libmultipath/prioritizers/ana.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/ana.c ++++ multipath-tools-130222/libmultipath/prioritizers/ana.c +@@ -165,7 +165,7 @@ int get_ana_info(struct path * pp, unsig + ana_log, ana_log_len); + pthread_cleanup_pop(1); + if (rc >= 0) +- condlog(3, "%s: ana state = %02x [%s]", pp->dev, rc, ++ condlog(4, "%s: ana state = %02x [%s]", pp->dev, rc, + aas_print_string(rc)); + return rc; + } diff --git a/SOURCES/0262-RHBZ-1699486-reload-with-failed-paths.patch b/SOURCES/0262-RHBZ-1699486-reload-with-failed-paths.patch new file mode 100644 index 0000000..0d560bd --- /dev/null +++ b/SOURCES/0262-RHBZ-1699486-reload-with-failed-paths.patch @@ -0,0 +1,67 @@ +--- + libmultipath/configure.c | 12 ++++++------ + libmultipath/discovery.c | 8 ++++++-- + multipathd/main.c | 1 + + 3 files changed, 13 insertions(+), 8 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1264,8 +1264,12 @@ get_prio (struct path * pp) + } + return 1; + } +- condlog(3, "%s: %s prio = %u", +- pp->dev, prio_name(p), pp->priority); ++ if (old_prio != PRIO_UNDEF && old_prio != pp->priority) ++ condlog(2, "%s: prio changed from %d to %d", pp->dev, ++ old_prio, pp->priority); ++ else ++ condlog(3, "%s: %s prio = %u", ++ pp->dev, prio_name(p), pp->priority); + return 0; + } + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1370,6 +1370,7 @@ int update_prio(struct path *pp, int ref + + int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh) + { ++ condlog(2, "%s: updating path groups %d", mpp->alias, refresh); + if (reload_map(vecs, mpp, refresh)) + return 1; + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -453,12 +453,6 @@ select_action (struct multipath * mpp, v + return; + } + +- if (pathcount(mpp, PATH_UP) == 0) { +- mpp->action = ACT_NOTHING; +- condlog(3, "%s: set ACT_NOTHING (no usable path)", +- mpp->alias); +- return; +- } + if (force_reload) { + mpp->force_udev_reload = 1; + mpp->action = ACT_RELOAD; +@@ -466,6 +460,12 @@ select_action (struct multipath * mpp, v + mpp->alias); + return; + } ++ if (pathcount(mpp, PATH_UP) == 0) { ++ mpp->action = ACT_NOTHING; ++ condlog(3, "%s: set ACT_NOTHING (no usable path)", ++ mpp->alias); ++ return; ++ } + if (cmpp->size != mpp->size) { + mpp->force_udev_reload = 1; + mpp->action = ACT_RESIZE; diff --git a/SOURCES/0263-RHBZ-1686708-nvme-hcil.patch b/SOURCES/0263-RHBZ-1686708-nvme-hcil.patch new file mode 100644 index 0000000..f7b1d2b --- /dev/null +++ b/SOURCES/0263-RHBZ-1686708-nvme-hcil.patch @@ -0,0 +1,36 @@ +--- + libmultipath/discovery.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -889,7 +889,7 @@ nvme_sysfs_pathinfo (struct path * pp) + { + struct udev_device *parent; + const char *attr_path = NULL; +- ++ const char *attr; + + attr_path = udev_device_get_sysname(pp->udev); + if (!attr_path) +@@ -902,10 +902,17 @@ nvme_sysfs_pathinfo (struct path * pp) + pp->sg_id.channel = 0; + pp->sg_id.lun = 0; + +- parent = udev_device_get_parent(pp->udev); ++ parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, ++ "nvme", NULL); + if (!parent) + return 1; + ++ attr = udev_device_get_sysattr_value(pp->udev, "nsid"); ++ pp->sg_id.lun = attr ? atoi(attr) : 0; ++ ++ attr = udev_device_get_sysattr_value(parent, "cntlid"); ++ pp->sg_id.channel = attr ? atoi(attr) : 0; ++ + snprintf(pp->vendor_id, SCSI_VENDOR_SIZE, "NVME"); + snprintf(pp->product_id, PATH_PRODUCT_SIZE, "%s", + udev_device_get_sysattr_value(parent, "model")); diff --git a/SOURCES/0264-RHBZ-1699441-de-series-config.patch b/SOURCES/0264-RHBZ-1699441-de-series-config.patch new file mode 100644 index 0000000..d05e5da --- /dev/null +++ b/SOURCES/0264-RHBZ-1699441-de-series-config.patch @@ -0,0 +1,28 @@ +--- + libmultipath/hwtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -748,6 +748,19 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_RDAC, + .prio_args = NULL, + }, ++ { ++ .vendor = "LENOVO", ++ .product = "DE_Series", ++ .bl_product = "Universal Xport", ++ .features = "2 pg_init_retries 50", ++ .hwhandler = "1 rdac", ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .no_path_retry = 30, ++ .checker_name = RDAC, ++ .prio_name = PRIO_RDAC, ++ .prio_args = NULL, ++ }, + /* + * NETAPP controller family + * diff --git a/SOURCES/0265-RHBZ-1721855-mpathpersist-speedup.patch b/SOURCES/0265-RHBZ-1721855-mpathpersist-speedup.patch new file mode 100644 index 0000000..70e2c3b --- /dev/null +++ b/SOURCES/0265-RHBZ-1721855-mpathpersist-speedup.patch @@ -0,0 +1,1175 @@ +--- + libmpathpersist/mpath_persist.c | 230 +++++++++++------------ + libmpathpersist/mpath_persist.h | 40 ++++ + mpathpersist/main.c | 223 ++++++++++++++++++----- + mpathpersist/main.h | 1 + mpathpersist/mpathpersist.8 | 385 ++++++++++++++++++++++++++++++---------- + 5 files changed, 616 insertions(+), 263 deletions(-) + +Index: multipath-tools-130222/mpathpersist/main.c +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.c ++++ multipath-tools-130222/mpathpersist/main.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + static const char * pr_type_strs[] = { + "obsolete [0]", +@@ -46,9 +47,101 @@ int construct_transportid(const char * i + int logsink; + unsigned int mpath_mx_alloc_len; + +-int main (int argc, char * argv[]) ++static int verbose, loglevel, noisy; ++ ++static int handle_args(int argc, char * argv[], int line); ++ ++static int do_batch_file(const char *batch_fn) + { +- int fd, c, res; ++ char command[] = "mpathpersist"; ++ const int ARGV_CHUNK = 2; ++ const char delims[] = " \t\n"; ++ size_t len = 0; ++ char *line = NULL; ++ ssize_t n; ++ int nline = 0; ++ int argl = ARGV_CHUNK; ++ FILE *fl; ++ char **argv = calloc(argl, sizeof(*argv)); ++ int ret = MPATH_PR_SUCCESS; ++ ++ if (argv == NULL) ++ return MPATH_PR_OTHER; ++ ++ fl = fopen(batch_fn, "r"); ++ if (fl == NULL) { ++ fprintf(stderr, "unable to open %s: %s\n", ++ batch_fn, strerror(errno)); ++ free(argv); ++ return MPATH_PR_SYNTAX_ERROR; ++ } else { ++ if (verbose >= 2) ++ fprintf(stderr, "running batch file %s\n", ++ batch_fn); ++ } ++ ++ while ((n = getline(&line, &len, fl)) != -1) { ++ char *_token, *token; ++ int argc = 0; ++ int rv; ++ ++ nline++; ++ argv[argc++] = command; ++ ++ if (line[n-1] == '\n') ++ line[n-1] = '\0'; ++ if (verbose >= 3) ++ fprintf(stderr, "processing line %d: %s\n", ++ nline, line); ++ ++ for (token = strtok_r(line, delims, &_token); ++ token != NULL && *token != '#'; ++ token = strtok_r(NULL, delims, &_token)) { ++ ++ if (argc >= argl) { ++ int argn = argl + ARGV_CHUNK; ++ char **tmp; ++ ++ tmp = realloc(argv, argn * sizeof(*argv)); ++ if (tmp == NULL) ++ break; ++ argv = tmp; ++ argl = argn; ++ } ++ ++ if (argc == 1 && !strcmp(token, command)) ++ continue; ++ ++ argv[argc++] = token; ++ } ++ ++ if (argc <= 1) ++ continue; ++ ++ if (verbose >= 2) { ++ int i; ++ ++ fprintf(stderr, "## file %s line %d:", batch_fn, nline); ++ for (i = 0; i < argc; i++) ++ fprintf(stderr, " %s", argv[i]); ++ fprintf(stderr, "\n"); ++ } ++ ++ optind = 0; ++ rv = handle_args(argc, argv, nline); ++ if (rv != MPATH_PR_SUCCESS) ++ ret = rv; ++ } ++ ++ fclose(fl); ++ free(argv); ++ free(line); ++ return ret; ++} ++ ++static int handle_args(int argc, char * argv[], int nline) ++{ ++ int fd, c; + const char *device_name = NULL; + int num_prin_sa = 0; + int num_prout_sa = 0; +@@ -69,45 +162,41 @@ int main (int argc, char * argv[]) + int prin = 1; + int prin_sa = -1; + int prout_sa = -1; +- int verbose = 0; +- int loglevel = 0; +- int noisy = 0; + int num_transport =0; ++ char *batch_fn = NULL; + void *resp = NULL; + struct transportid * tmp; +- struct udev *udev = NULL; + +- if (optind == argc) +- { +- +- fprintf (stderr, "No parameter used\n"); +- usage (); +- exit (1); +- } +- +- if (getuid () != 0) +- { +- fprintf (stderr, "need to be root\n"); +- exit (1); +- } +- +- udev = udev_new(); +- mpath_lib_init(udev); +- memset(transportids,0,MPATH_MX_TIDS); ++ memset(transportids, 0, MPATH_MX_TIDS * sizeof(struct transportid)); + + while (1) + { + int option_index = 0; + +- c = getopt_long (argc, argv, "v:Cd:hHioZK:S:PAT:skrGILcRX:l:", ++ c = getopt_long (argc, argv, "v:Cd:hHioZK:S:PAT:skrGILcRX:l:f:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { ++ case 'f': ++ if (nline != 0) { ++ fprintf(stderr, ++ "ERROR: -f option not allowed in batch file\n"); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; ++ } ++ if (batch_fn != NULL) { ++ fprintf(stderr, ++ "ERROR: -f option can be used at most once\n"); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; ++ } ++ batch_fn = strdup(optarg); ++ break; + case 'v': +- if (1 != sscanf (optarg, "%d", &loglevel)) ++ if (nline == 0 && 1 != sscanf (optarg, "%d", &loglevel)) + { + fprintf (stderr, "bad argument to '--verbose'\n"); + return MPATH_PR_SYNTAX_ERROR; +@@ -241,8 +330,7 @@ int main (int argc, char * argv[]) + break; + + default: +- fprintf(stderr, "unrecognised switch " "code 0x%x ??\n", c); +- usage (); ++ fprintf(stderr, "unrecognised switch " "code 0x%x ??\n", c); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } +@@ -260,27 +348,29 @@ int main (int argc, char * argv[]) + { + for (; optind < argc; ++optind) + fprintf (stderr, "Unexpected extra argument: %s\n", argv[optind]); +- usage (); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } + } + +- /* set verbosity */ +- noisy = (loglevel >= 3) ? 1 : hex; +- verbose = (loglevel >= 4)? 4 : loglevel; ++ if (nline == 0) { ++ /* set verbosity */ ++ noisy = (loglevel >= 3) ? 1 : hex; ++ verbose = (loglevel >= 4)? 4 : loglevel; ++ ret = mpath_persistent_reserve_init_vecs(verbose); ++ if (ret != MPATH_PR_SUCCESS) ++ goto out; ++ } + +- if ((prout_flag + prin_flag) == 0) ++ if ((prout_flag + prin_flag) == 0 && batch_fn == NULL) + { + fprintf (stderr, "choose either '--in' or '--out' \n"); +- usage (); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } + if ((prout_flag + prin_flag) > 1) + { + fprintf (stderr, "choose either '--in' or '--out' \n"); +- usage (); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } +@@ -311,21 +401,19 @@ int main (int argc, char * argv[]) + { + fprintf (stderr, + " No service action given for Persistent Reserve IN\n"); +- usage(); + ret = MPATH_PR_SYNTAX_ERROR; + } + else if (num_prin_sa > 1) + { + fprintf (stderr, " Too many service actions given; choose " + "one only\n"); +- usage(); + ret = MPATH_PR_SYNTAX_ERROR; + } + } + else + { +- usage (); +- ret = MPATH_PR_SYNTAX_ERROR; ++ if (batch_fn == NULL) ++ ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } + +@@ -333,7 +421,6 @@ int main (int argc, char * argv[]) + { + fprintf (stderr, " --relative-target-port" + " only useful with --register-move\n"); +- usage (); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } +@@ -355,7 +442,6 @@ int main (int argc, char * argv[]) + if (device_name == NULL) + { + fprintf (stderr, "No device name given \n"); +- usage (); + ret = MPATH_PR_SYNTAX_ERROR; + goto out; + } +@@ -382,7 +468,7 @@ int main (int argc, char * argv[]) + goto out; + } + +- ret = mpath_persistent_reserve_in (fd, prin_sa, resp, noisy, verbose); ++ ret = __mpath_persistent_reserve_in (fd, prin_sa, resp, noisy); + if (ret != MPATH_PR_SUCCESS ) + { + fprintf (stderr, "Persistent Reserve IN command failed\n"); +@@ -442,8 +528,8 @@ int main (int argc, char * argv[]) + } + + /* PROUT commands other than 'register and move' */ +- ret = mpath_persistent_reserve_out (fd, prout_sa, 0, prout_type, +- paramp, noisy, verbose); ++ ret = __mpath_persistent_reserve_out (fd, prout_sa, 0, prout_type, ++ paramp, noisy); + for (j = 0 ; j < num_transport; j++) + { + tmp = paramp->trnptid_list[j]; +@@ -466,17 +552,57 @@ int main (int argc, char * argv[]) + printf("PR out: command failed\n"); + } + +- res = close (fd); +- if (res < 0) ++ close (fd); ++ ++out : ++ if (ret == MPATH_PR_SYNTAX_ERROR) { ++ free(batch_fn); ++ if (nline == 0) ++ usage(); ++ else ++ fprintf(stderr, "syntax error on line %d in batch file\n", ++ nline); ++ } else if (batch_fn != NULL) { ++ int rv = do_batch_file(batch_fn); ++ ++ free(batch_fn); ++ ret = ret == 0 ? rv : ret; ++ } ++ if (nline == 0) ++ mpath_persistent_reserve_free_vecs(); ++ return (ret >= 0) ? ret : MPATH_PR_OTHER; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct udev *udev; ++ int ret; ++ ++ if (optind == argc) ++ { ++ ++ fprintf (stderr, "No parameter used\n"); ++ usage (); ++ exit (1); ++ } ++ ++ if (getuid () != 0) + { +- mpath_lib_exit(); ++ fprintf (stderr, "need to be root\n"); ++ exit (1); ++ } ++ ++ udev = udev_new(); ++ if(mpath_lib_init(udev) != 0) { + udev_unref(udev); +- return MPATH_PR_FILE_ERROR; ++ exit(1); + } + +-out : ++ ret = handle_args(argc, argv, 0); ++ + mpath_lib_exit(); + udev_unref(udev); ++ + return (ret >= 0) ? ret : MPATH_PR_OTHER; + } + +@@ -677,6 +803,7 @@ static void usage() + " 4 Informational messages with trace enabled\n" + " --clear|-C PR Out: Clear\n" + " --device=DEVICE|-d DEVICE query or change DEVICE\n" ++ " --batch-file|-f FILE run commands from FILE\n" + " --help|-h output this usage message\n" + " --hex|-H output response in hex\n" + " --in|-i request PR In command \n" +Index: multipath-tools-130222/mpathpersist/main.h +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.h ++++ multipath-tools-130222/mpathpersist/main.h +@@ -2,6 +2,7 @@ static struct option long_options[] = { + {"verbose", 1, 0, 'v'}, + {"clear", 0, 0, 'C'}, + {"device", 1, 0, 'd'}, ++ {"batch-file", 1, 0, 'f' }, + {"help", 0, 0, 'h'}, + {"hex", 0, 0, 'H'}, + {"in", 0, 0, 'i'}, +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -80,17 +81,21 @@ updatepaths (struct multipath * mpp) + pp->state = PATH_DOWN; + continue; + } +- pp->mpp = mpp; +- pathinfo(pp, conf->hwtable, DI_ALL); +- continue; + } + pp->mpp = mpp; ++ if (pp->udev == NULL) { ++ pp->udev = udev_device_new_from_devnum(conf->udev, 'b', parse_devt(pp->dev_t)); ++ if (pp->udev == NULL) { ++ pp->state = PATH_DOWN; ++ continue; ++ } ++ pathinfo(pp, conf->hwtable, ++ DI_SYSFS|DI_CHECKER); ++ continue; ++ } + if (pp->state == PATH_UNCHECKED || + pp->state == PATH_WILD) + pathinfo(pp, conf->hwtable, DI_CHECKER); +- +- if (pp->priority == PRIO_UNDEF) +- pathinfo(pp, conf->hwtable, DI_PRIO); + } + } + return 0; +@@ -129,45 +134,44 @@ mpath_prin_activepath (struct multipath + + int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp *resp, int noisy, int verbose) + { +- struct stat info; +- vector curmp = NULL; +- vector pathvec = NULL; +- char * alias; +- struct multipath * mpp; +- int map_present; +- int major, minor; +- int ret; ++ int ret = mpath_persistent_reserve_init_vecs(verbose); + +- conf->verbosity = verbose; ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy); ++ mpath_persistent_reserve_free_vecs(); ++ return ret; ++} + +- if (fstat( fd, &info) != 0){ +- condlog(0, "stat error %d", fd); +- return MPATH_PR_FILE_ERROR; +- } +- if(!S_ISBLK(info.st_mode)){ +- condlog(0, "Failed to get major:minor. fd = %d", fd); +- return MPATH_PR_FILE_ERROR; +- } ++int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, ++ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose) ++{ ++ int ret = mpath_persistent_reserve_init_vecs(verbose); + +- major = (int)MAJOR(info.st_rdev); +- minor = (int)MINOR(info.st_rdev); +- condlog(4, "Device %d:%d: ", major, minor); ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type, ++ paramp, noisy); ++ mpath_persistent_reserve_free_vecs(); ++ return ret; ++} + +- /* get alias from major:minor*/ +- alias = dm_mapname(major, minor); +- if (!alias){ +- condlog(0, "%d:%d failed to get device alias.", major, minor); +- return MPATH_PR_DMMP_ERROR; +- } ++static vector curmp; ++static vector pathvec; + +- condlog(3, "alias = %s", alias); +- map_present = dm_map_present(alias); +- if (map_present && !dm_is_mpath(alias)){ +- condlog( 0, "%s: not a multipath device.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out; +- } ++void mpath_persistent_reserve_free_vecs(void) ++{ ++ free_multipathvec(curmp, KEEP_PATHS); ++ free_pathvec(pathvec, FREE_PATHS); ++ curmp = pathvec = NULL; ++} ++ ++int mpath_persistent_reserve_init_vecs(int verbose) ++{ ++ conf->verbosity = verbose; + ++ if (curmp) ++ return MPATH_PR_SUCCESS; + /* + * allocate core vectors to store paths and multipaths + */ +@@ -175,63 +179,32 @@ int mpath_persistent_reserve_in (int fd, + pathvec = vector_alloc (); + + if (!curmp || !pathvec){ +- condlog (0, "%s: vector allocation failed.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out; +- } +- +- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; +- } +- +- /* get info of all paths from the dm device */ +- if (get_mpvec (curmp, pathvec, alias)){ +- condlog(0, "%s: failed to get device info.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; ++ condlog (0, "vector allocation failed."); ++ goto err; + } + +- mpp = find_mp_by_alias(curmp, alias); +- if (!mpp){ +- condlog(0, "%s: devmap not registered.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; +- } ++ if (dm_get_maps(curmp)) ++ goto err; + +- ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy); ++ return MPATH_PR_SUCCESS; + +-out1: +- free_multipathvec(curmp, KEEP_PATHS); +- free_pathvec(pathvec, FREE_PATHS); +-out: +- FREE(alias); +- return ret; ++err: ++ mpath_persistent_reserve_free_vecs(); ++ return MPATH_PR_DMMP_ERROR; + } + +-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, +- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose) ++static int mpath_get_map(int fd, char **palias, struct multipath **pmpp) + { +- ++ int ret = MPATH_PR_DMMP_ERROR; + struct stat info; +- +- vector curmp = NULL; +- vector pathvec = NULL; +- +- char * alias; +- struct multipath * mpp; +- int map_present; + int major, minor; +- int ret; +- uint64_t prkey; +- +- conf->verbosity = verbose; ++ char *alias; ++ struct multipath *mpp; + +- if (fstat( fd, &info) != 0){ ++ if (fstat(fd, &info) != 0){ + condlog(0, "stat error fd=%d", fd); + return MPATH_PR_FILE_ERROR; + } +- + if(!S_ISBLK(info.st_mode)){ + condlog(3, "Failed to get major:minor. fd=%d", fd); + return MPATH_PR_FILE_ERROR; +@@ -241,53 +214,72 @@ int mpath_persistent_reserve_out ( int f + minor = (int)MINOR(info.st_rdev); + condlog(4, "Device %d:%d", major, minor); + +- /* get WWN of the device from major:minor*/ ++ /* get alias from major:minor*/ + alias = dm_mapname(major, minor); + if (!alias){ ++ condlog(0, "%d:%d failed to get device alias.", major, minor); + return MPATH_PR_DMMP_ERROR; + } + + condlog(3, "alias = %s", alias); +- map_present = dm_map_present(alias); + +- if (map_present && !dm_is_mpath(alias)){ ++ if (dm_map_present(alias) && !dm_is_mpath(alias)){ + condlog(3, "%s: not a multipath device.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out; +- } +- +- /* +- * allocate core vectors to store paths and multipaths +- */ +- curmp = vector_alloc (); +- pathvec = vector_alloc (); +- +- if (!curmp || !pathvec){ +- condlog (0, "%s: vector allocation failed.", alias); +- ret = MPATH_PR_DMMP_ERROR; + goto out; + } + +- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; +- } +- + /* get info of all paths from the dm device */ + if (get_mpvec(curmp, pathvec, alias)){ + condlog(0, "%s: failed to get device info.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; ++ goto out; + } + + mpp = find_mp_by_alias(curmp, alias); + + if (!mpp) { + condlog(0, "%s: devmap not registered.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out1; ++ goto out; + } + ++ ret = MPATH_PR_SUCCESS; ++ if (pmpp) ++ *pmpp = mpp; ++ if (palias) { ++ *palias = alias; ++ alias = NULL; ++ } ++out: ++ FREE(alias); ++ return ret; ++} ++ ++int __mpath_persistent_reserve_in (int fd, int rq_servact, ++ struct prin_resp *resp, int noisy) ++{ ++ struct multipath *mpp; ++ int ret; ++ ++ ret = mpath_get_map(fd, NULL, &mpp); ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ ++ ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy); ++ ++ return ret; ++} ++ ++int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, ++ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy) ++{ ++ struct multipath *mpp; ++ char *alias; ++ int ret; ++ uint64_t prkey; ++ ++ ret = mpath_get_map(fd, &alias, &mpp); ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ + select_reservation_key(mpp); + select_all_tg_pt(mpp); + +@@ -350,10 +342,6 @@ int mpath_persistent_reserve_out ( int f + } + } + out1: +- free_multipathvec(curmp, KEEP_PATHS); +- free_pathvec(pathvec, FREE_PATHS); +- +-out: + FREE(alias); + return ret; + } +@@ -365,21 +353,22 @@ get_mpvec (vector curmp, vector pathvec, + struct multipath *mpp; + char params[PARAMS_SIZE], status[PARAMS_SIZE]; + +- if (dm_get_maps (curmp)){ +- return 1; +- } +- + vector_foreach_slot (curmp, mpp, i){ + /* + * discard out of scope maps + */ +- if (mpp->alias && refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE)){ +- free_multipath (mpp, KEEP_PATHS); +- vector_del_slot (curmp, i); +- i--; ++ if (!mpp->alias) { ++ condlog(0, "%s: map with empty alias!", __func__); + continue; + } + ++ if (mpp->pg != NULL) ++ /* Already seen this one */ ++ continue; ++ ++ if (refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE - 1)) ++ continue; ++ + dm_get_map(mpp->alias, &mpp->size, params); + condlog(3, "params = %s", params); + dm_get_status(mpp->alias, status); +@@ -392,7 +381,6 @@ get_mpvec (vector curmp, vector pathvec, + * about them + */ + updatepaths(mpp); +- mpp->bestpg = select_path_group (mpp); + disassemble_status (status, mpp); + + } +Index: multipath-tools-130222/libmpathpersist/mpath_persist.h +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.h ++++ multipath-tools-130222/libmpathpersist/mpath_persist.h +@@ -212,6 +212,15 @@ extern int mpath_persistent_reserve_in ( + + /* + * DESCRIPTION : ++ * This function is like mpath_persistent_reserve_in(), except that it doesn't call ++ * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs() ++ * before and after the actual PR call. ++ */ ++extern int __mpath_persistent_reserve_in(int fd, int rq_servact, ++ struct prin_resp *resp, int noisy); ++ ++/* ++ * DESCRIPTION : + * This function sends PROUT command to the DM device and get the response. + * + * @fd: The file descriptor of a multipath device. Input argument. +@@ -235,6 +244,37 @@ extern int mpath_persistent_reserve_in ( + extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, + int verbose); ++/* ++ * DESCRIPTION : ++ * This function is like mpath_persistent_reserve_out(), except that it doesn't call ++ * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs() ++ * before and after the actual PR call. ++ */ ++extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope, ++ unsigned int rq_type, struct prout_param_descriptor *paramp, ++ int noisy); ++ ++/* ++ * DESCRIPTION : ++ * This function allocates data structures and performs basic initialization and ++ * device discovery for later calls of __mpath_persistent_reserve_in() or ++ * __mpath_persistent_reserve_out(). ++ * @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose ++ * ++ * RESTRICTIONS: ++ * ++ * RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified ++ * above in RETURN_STATUS. ++ */ ++int mpath_persistent_reserve_init_vecs(int verbose); ++ ++/* ++ * DESCRIPTION : ++ * This function frees data structures allocated by ++ * mpath_persistent_reserve_init_vecs(). ++ */ ++void mpath_persistent_reserve_free_vecs(void); ++ + + #ifdef __cplusplus + } +Index: multipath-tools-130222/mpathpersist/mpathpersist.8 +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/mpathpersist.8 ++++ multipath-tools-130222/mpathpersist/mpathpersist.8 +@@ -1,99 +1,296 @@ +-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.39.2. +-.TH MPATHPERSIST "8" "April 2011" "mpathpersist" "User Commands" ++.\" ---------------------------------------------------------------------------- ++.\" Update the date below if you make any significant change. ++.\" Make sure there are no errors with: ++.\" groff -z -wall -b -e -t mpathpersist/mpathpersist.8 ++.\" ++.\" ---------------------------------------------------------------------------- ++. ++.TH MPATHPERSIST 8 2019-05-27 "Linux" ++. ++. ++.\" ---------------------------------------------------------------------------- + .SH NAME +-mpathpersist ++.\" ---------------------------------------------------------------------------- ++. ++mpathpersist \- Manages SCSI persistent reservations on dm multipath devices. ++. ++. ++.\" ---------------------------------------------------------------------------- + .SH SYNOPSIS ++.\" ---------------------------------------------------------------------------- ++. + .B mpathpersist +-[\fIOPTIONS\fR] [\fIDEVICE\fR] ++.RB [\| OPTIONS \|] ++.I device ++. ++. ++.\" ---------------------------------------------------------------------------- + .SH DESCRIPTION +-.IP +-Options: +-.TP +-\fB\-\-verbose\fR|\-v level +-verbosity level +-.TP +-0 +-Critical and error messages +-.TP +-1 +-Warning messages +-.TP +-2 +-Informational messages +-.TP +-3 +-Informational messages with trace enabled +-.TP +-\fB\-\-clear\fR|\-C +-PR Out: Clear +-.TP +-\fB\-\-device\fR=\fIDEVICE\fR|\-d DEVICE +-query or change DEVICE +-.TP +-\fB\-\-help\fR|\-h +-output this usage message +-.TP +-\fB\-\-hex\fR|\-H +-output response in hex +-.TP +-\fB\-\-in\fR|\-i +-request PR In command +-.TP +-\fB\-\-out\fR|\-o +-request PR Out command +-.TP +-\fB\-\-param\-aptpl\fR|\-Z +-PR Out parameter 'APTPL' +-.TP +-\fB\-\-read\-keys\fR|\-k +-PR In: Read Keys +-.TP +-\fB\-\-param\-rk\fR=\fIRK\fR|\-K RK +-PR Out parameter reservation key (RK is in hex) +-.TP +-\fB\-\-param\-sark\fR=\fISARK\fR|\-S SARK +-PR Out parameter service action +-reservation key (SARK is in hex) +-.TP +-\fB\-\-preempt\fR|\-P +-PR Out: Preempt +-.TP +-\fB\-\-preempt\-abort\fR|\-A +-PR Out: Preempt and Abort +-.TP +-\fB\-\-prout\-type\fR=\fITYPE\fR|\-T TYPE +-PR Out command type +-.TP +-\fB\-\-read\-status\fR|\-s +-PR In: Read Full Status +-.TP +-\fB\-\-read\-keys\fR|\-k +-PR In: Read Keys +-.TP +-\fB\-\-read\-reservation\fR|\-r +-PR In: Read Reservation +-.TP +-\fB\-\-register\fR|\-G +-PR Out: Register +-.TP +-\fB\-\-register\-ignore\fR|\-I +-PR Out: Register and Ignore +-.TP +-\fB\-\-release\fR|\-L +-PR Out: Release +-.TP +-\fB\-\-report\-capabilities\fR|\-c +-PR In: Report Capabilities +-.TP +-\fB\-\-reserve\fR|\-R +-PR Out: Reserve +-.TP +-\fB\-\-transport\-id\fR=\fITIDS\fR|\-X TIDS +-TransportIDs can be mentioned +-in several forms +-.IP +-Examples: +-.IP +-mpathpersist \fB\-\-out\fR \fB\-\-register\fR \fB\-\-param\-sark\fR=\fI123abc\fR \fB\-\-prout\-type\fR=\fI5\fR /dev/mapper/mpath9 +-mpathpersist \fB\-i\fR \fB\-k\fR /dev/mapper/mpath9 ++.\" ---------------------------------------------------------------------------- ++. ++This utility is used to manage SCSI persistent reservations on Device Mapper ++Multipath devices. To be able to use this functionality, the \fIreservation_key\fR ++attribute must be defined in the \fI/etc/multipath.conf\fR file. Otherwise the ++\fBmultipathd\fR daemon will not check for persistent reservation for newly ++discovered paths or reinstated paths. ++. ++.LP ++\fBmpathpersist\fR supports the same command-line options as the ++\fBsg_persist\fR utility. ++. ++Consult the \fBsg_persist (8)\fR manual page for an in-depth discussion of the ++various options. ++. ++.\" ---------------------------------------------------------------------------- ++.SH OPTIONS ++.\" ---------------------------------------------------------------------------- ++. ++.TP ++.BI \-verbose|\-v " level" ++Verbosity: ++.RS ++.TP 5 ++.I 0 ++Critical messages. ++.TP ++.I 1 ++Error messages. ++.TP ++.I 2 ++Warning messages. ++.TP ++.I 3 ++Informational messages. ++.TP ++.I 4 ++Informational messages with trace enabled. ++.RE ++. ++.TP ++.BI \--device=\fIDEVICE\fB|\-d " DEVICE" ++Query or change DEVICE. ++. ++.TP ++.BI \--batch-file=\fIDEVICE\fB|\-f " FILE" ++Read commands from \fIFILE\fR. See section \(dqBATCH FILES\(dq below. This ++option can be given at most once. ++. ++.TP ++.B \--help|\-h ++Output this usage message. ++. ++.TP ++.B \--hex|\-H ++Output response in hex. ++. ++.TP ++.B \--in|\-i ++Request PR In command. ++. ++.TP ++.B \--out|\-o ++Request PR Out command. ++. ++.TP ++.B \--param-aptpl|\-Z ++PR Out parameter 'APTPL'. ++. ++.TP ++.B \--read-keys|\-k ++PR In: Read Keys. ++. ++.TP ++.BI \--param-rk=\fIRK\fB|\-K " RK" ++PR Out parameter reservation key (RK is in hex, up to 8 bytes). ++. ++.TP ++.BI \--param-sark=\fISARK\fB|\-S " SARK" ++PR Out parameter service action reservation key (SARK is in hex). ++. ++.TP ++.B \--preempt|\-P ++PR Out: Preempt. ++. ++.TP ++.B \--clear|\-C ++PR Out: Clear registrations. ++. ++.TP ++.B \--preempt-abort|\-A ++PR Out: Preempt and Abort. ++. ++.TP ++.BI \--prout-type=\fITYPE\fB|\-T " TYPE" ++PR Out command type. ++. ++.TP ++.B \--read-full-status|\-s ++PR In: Read Full Status. ++. ++.TP ++.B \--read-keys|\-k ++PR In: Read Keys. ++. ++.TP ++.B \--read-reservation|\-r ++PR In: Read Reservation. ++. ++.TP ++.B \--register|\-G ++PR Out: Register. ++. ++.TP ++.B \--register-ignore|\-I ++PR Out: Register and Ignore. ++. ++.TP ++.B \--release|\-L ++PR Out: Release. ++. ++.TP ++.B \--report-capabilities|\-c ++PR In: Report Capabilities. ++. ++.TP ++.B \--reserve|\-R ++PR Out: Reserve. ++. ++.TP ++.BI \--transport-id=\fITIDS\fB|\-X " TIDS" ++TransportIDs can be mentioned in several forms. ++. ++.TP ++.BI \--alloc-length=\fILEN\fB|\-l " LEN" ++PR In: maximum allocation length. LEN is a decimal number between 0 and 8192. ++. ++. ++.\" ---------------------------------------------------------------------------- ++.SH EXAMPLE ++.\" ---------------------------------------------------------------------------- ++. ++.PP ++Register the key \(dq123abc\(dq for the /dev/mapper/mpath9 device: ++.RS ++\fBmpathpersist --out --register --param-sark=\fI123abc /dev/mapper/mpath9\fR ++.RE ++.PP ++Read registered reservation keys for the /dev/mapper/mpath9 device: ++.RS ++\fBmpathpersist -i -k \fI/dev/mapper/mpath9\fR ++.RE ++.PP ++Create a reservation for the /dev/mapper/mpath9 device with the given ++reservation key: ++.RS ++\fBmpathpersist --out --reserve --param-rk=\fI123abc \fB--prout-type=\fI8 \fB-d \fI/dev/mapper/mpath9\fR ++.RE ++.PP ++Read the reservation status of the /dev/mapper/mpath9 device: ++.RS ++\fBmpathpersist -i -s -d \fI/dev/mapper/mpath9\fR ++.RE ++.PP ++Release the previously created reservation (note that the prout-type needs to ++be the same as above): ++.RS ++\fBmpathpersist --out --release --param-rk=\fI123abc \fB--prout-type=\fI8 \fB-d \fI/dev/mapper/mpath9\fR ++.RE ++.PP ++Remove the current key registered for this host (i.e. reset it to 0): ++.RS ++\fBmpathpersist --out --register-ignore -K \fI123abc\fB -S \fI0\fB \fI/dev/mapper/mpath9\fR ++.RE ++.PP ++Remove current reservation, and unregister all registered keys from all I_T nexuses: ++.RS ++\fBmpathpersist -oCK \fI123abc \fI/dev/mapper/mpath9\fR ++.RE ++. ++. ++.\" ---------------------------------------------------------------------------- ++.SH BATCH FILES ++.\" ---------------------------------------------------------------------------- ++. ++.PP ++The option \fI--batch-file\fR (\fI-f\fR) sets an input file to be processed ++by \fBmpathpersist\fR. Grouping commands in batch files can provide a speed ++improvement in particular on large installments, because \fBmpathpersist\fR ++needs to scan existing paths and maps only once during startup. ++. ++.PP ++The input file is a text file that is parsed ++line by line. Every line of the file is interpreted as a command line ++(i.e. list of options and parameters) for \fBmpathpersist\fR. Options ++and parameters are separated by one or more whitespace characters (space or TAB). ++Lines can, but do not have to, begin with the word \(dqmpathpersist\(dq. ++The \(dq#\(dq character, either at the beginning of the line or following ++some whitespace, denotes the start of a comment that lasts until the end of the ++line. Empty lines are allowed. Continuation of mpathpersist commands over ++multiple lines is not supported. ++. ++.PP ++All options listed in this man page, except \fI-f\fR and ++\fI-v\fR, are allowed in batch files. Both short and long option formats may be used. ++Using the \fI-f\fR option inside the batch file is an error. The \fI-v\fR ++option is ignored in batch files. ++. ++.PP ++The multipath map on which to act must be specified on every input line, e.g. using the \fI-d\fR option. ++Commands acting on different multipath maps may be combined in a ++batch file, and multiple commands may act on the same multipath ++map. Commands are executed one by one, so ++that commands further down in the file see status changes caused by previous ++commands. ++If \fBmpathpersist\fR encounters an error while processing a line in the ++batch file, batch file processing is \fBnot\fR aborted; subsequent commands ++are executed nonetheless. The exit status of \fBmpathpersist\fR is the status ++of the first failed command, or 0 if all commands succeeded. ++. ++.PP ++If other options and parameters are used along with ++\fI-f\fR on the \fBmpathpersist\fR command line, the command line will be executed first, followed ++by the commands from the the batch file. ++. ++.PP ++Below is an example of a valid batch input file. ++. + .PP ++.RS ++.EX ++# This is an mpathpersist input file. ++# Short and long forms of the same command ++-i -k /dev/dm-1 # short form, this comment is ignored ++mpathpersist --in --read-keys --device=/dev/dm-1 ++ ++# Mixing of long and short options, variable white space ++ --out --register -S abcde /dev/dm-1 ++ ++# Mixing of commands for different maps ++-ir /dev/dm-0 ++-ir /dev/dm-1 ++ ++mpathpersist --out --param-rk abcde --reserve --prout-type 5 /dev/dm-1 ++# This should now show a reservation ++-ir /dev/dm-1 ++-oCK abcde /dev/dm-1 ++--in --read-reservation /dev/dm-1 ++.EE ++.RE ++. ++. ++.\" ---------------------------------------------------------------------------- ++.SH "SEE ALSO" ++.\" ---------------------------------------------------------------------------- ++. ++.BR multipath (8), ++.BR multipathd (8), ++.BR sg_persist (8). ++. ++. ++.\" ---------------------------------------------------------------------------- ++.SH AUTHORS ++.\" ---------------------------------------------------------------------------- ++. ++\fImultipath-tools\fR was developed by Christophe Varoqui ++and others. ++.\" EOF diff --git a/SOURCES/0266-RHBZ-1696817-fix-emc-checker.patch b/SOURCES/0266-RHBZ-1696817-fix-emc-checker.patch new file mode 100644 index 0000000..c7bf33a --- /dev/null +++ b/SOURCES/0266-RHBZ-1696817-fix-emc-checker.patch @@ -0,0 +1,219 @@ +--- + libmultipath/checkers.c | 29 +++++++++++++++++++++++++++-- + libmultipath/checkers.h | 2 ++ + libmultipath/checkers/cciss_tur.c | 5 +++++ + libmultipath/checkers/directio.c | 5 +++++ + libmultipath/checkers/emc_clariion.c | 7 +++++++ + libmultipath/checkers/hp_sw.c | 5 +++++ + libmultipath/checkers/rdac.c | 5 +++++ + libmultipath/checkers/readsector0.c | 5 +++++ + libmultipath/checkers/tur.c | 5 +++++ + libmultipath/discovery.c | 2 ++ + 10 files changed, 68 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/checkers.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.c ++++ multipath-tools-130222/libmultipath/checkers.c +@@ -132,6 +132,13 @@ struct checker * add_checker (char * nam + if (!c->init) + goto out; + ++ c->mp_init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_mp_init"); ++ errstr = dlerror(); ++ if (errstr != NULL) ++ condlog(0, "A dynamic linking error occurred: (%s)", errstr); ++ if (!c->mp_init) ++ goto out; ++ + c->free = (void (*)(struct checker *)) dlsym(c->handle, "libcheck_free"); + errstr = dlerror(); + if (errstr != NULL) +@@ -189,8 +196,25 @@ int checker_init (struct checker * c, vo + if (!c) + return 1; + c->mpcontext = mpctxt_addr; +- if (c->init) +- return c->init(c); ++ if (c->init && c->init(c) != 0) ++ return 1; ++ if (mpctxt_addr && *mpctxt_addr == NULL && c->mp_init && ++ c->mp_init(c) != 0) /* for now, continue even if mp_init fails */ ++ c->mpcontext = NULL; ++ return 0; ++} ++ ++int checker_mp_init(struct checker * c, void ** mpctxt_addr) ++{ ++ if (!c) ++ return 1; ++ if (c->mp_init && !c->mpcontext && mpctxt_addr) { ++ c->mpcontext = mpctxt_addr; ++ if (c->mp_init(c) != 0) { ++ c->mpcontext = NULL; ++ return 1; ++ } ++ } + return 0; + } + +@@ -277,6 +301,7 @@ void checker_get (struct checker * dst, + strncpy(dst->message, src->message, CHECKER_MSG_LEN); + dst->check = src->check; + dst->init = src->init; ++ dst->mp_init = src->mp_init; + dst->free = src->free; + dst->handle = NULL; + src->refcount++; +Index: multipath-tools-130222/libmultipath/checkers.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.h ++++ multipath-tools-130222/libmultipath/checkers.h +@@ -107,6 +107,7 @@ struct checker { + you want to stuff data in. */ + int (*check)(struct checker *); + int (*init)(struct checker *); /* to allocate the context */ ++ int (*mp_init)(struct checker *); /* to allocate the mpcontext */ + void (*free)(struct checker *); /* to free the context */ + }; + +@@ -118,6 +119,7 @@ void cleanup_checkers (void); + struct checker * add_checker (char *); + struct checker * checker_lookup (char *); + int checker_init (struct checker *, void **); ++int checker_mp_init (struct checker *, void **); + void checker_put (struct checker *); + void checker_reset (struct checker *); + void checker_set_sync (struct checker *); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1217,6 +1217,8 @@ get_state (struct path * pp, int daemon, + return PATH_UNCHECKED; + } + } ++ if (pp->mpp && !c->mpcontext) ++ checker_mp_init(c, &pp->mpp->mpcontext); + checker_clear_message(c); + if (daemon) { + if (conf->force_sync == 0) +Index: multipath-tools-130222/libmultipath/checkers/cciss_tur.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/cciss_tur.c ++++ multipath-tools-130222/libmultipath/checkers/cciss_tur.c +@@ -58,6 +58,11 @@ int libcheck_init (struct checker * c) + return 0; + } + ++int libcheck_mp_init (struct checker * c) ++{ ++ return 0; ++} ++ + void libcheck_free (struct checker * c) + { + return; +Index: multipath-tools-130222/libmultipath/checkers/directio.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/directio.c ++++ multipath-tools-130222/libmultipath/checkers/directio.c +@@ -94,6 +94,11 @@ out: + return 1; + } + ++int libcheck_mp_init(struct checker * c) ++{ ++ return 0; ++} ++ + void libcheck_free (struct checker * c) + { + struct directio_context * ct = (struct directio_context *)c->context; +Index: multipath-tools-130222/libmultipath/checkers/emc_clariion.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/emc_clariion.c ++++ multipath-tools-130222/libmultipath/checkers/emc_clariion.c +@@ -73,11 +73,18 @@ int libcheck_init (struct checker * c) + return 1; + ((struct emc_clariion_checker_path_context *)c->context)->wwn_set = 0; + ++ return 0; ++} ++ ++int libcheck_mp_init (struct checker * c) ++{ + /* + * Allocate and initialize the multi-path global context. + */ + if (c->mpcontext && *c->mpcontext == NULL) { + void * mpctxt = malloc(sizeof(int)); ++ if (!mpctxt) ++ return 1; + *c->mpcontext = mpctxt; + CLR_INACTIVE_SNAP(c); + } +Index: multipath-tools-130222/libmultipath/checkers/hp_sw.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/hp_sw.c ++++ multipath-tools-130222/libmultipath/checkers/hp_sw.c +@@ -39,6 +39,11 @@ int libcheck_init (struct checker * c) + return 0; + } + ++int libcheck_mp_init(struct checker * c) ++{ ++ return 0; ++} ++ + void libcheck_free (struct checker * c) + { + return; +Index: multipath-tools-130222/libmultipath/checkers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/rdac.c ++++ multipath-tools-130222/libmultipath/checkers/rdac.c +@@ -134,6 +134,11 @@ out: + return 0; + } + ++int libcheck_mp_init(struct checker * c) ++{ ++ return 0; ++} ++ + void libcheck_free (struct checker * c) + { + return; +Index: multipath-tools-130222/libmultipath/checkers/readsector0.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/readsector0.c ++++ multipath-tools-130222/libmultipath/checkers/readsector0.c +@@ -18,6 +18,11 @@ int libcheck_init (struct checker * c) + return 0; + } + ++int libcheck_mp_init(struct checker * c) ++{ ++ return 0; ++} ++ + void libcheck_free (struct checker * c) + { + return; +Index: multipath-tools-130222/libmultipath/checkers/tur.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/tur.c ++++ multipath-tools-130222/libmultipath/checkers/tur.c +@@ -158,6 +158,11 @@ int libcheck_init (struct checker * c) + return 0; + } + ++int libcheck_mp_init(struct checker * c) ++{ ++ return 0; ++} ++ + void cleanup_context(struct tur_checker_context *ct) + { + pthread_mutex_destroy(&ct->lock); diff --git a/SOURCES/0267-RHBZ-1661156-powermax-config.patch b/SOURCES/0267-RHBZ-1661156-powermax-config.patch new file mode 100644 index 0000000..5b90501 --- /dev/null +++ b/SOURCES/0267-RHBZ-1661156-powermax-config.patch @@ -0,0 +1,23 @@ +--- + libmultipath/hwtable.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1194,6 +1194,14 @@ static struct hwentry default_hw[] = { + .detect_prio = DETECT_PRIO_ON, + .checker_name = NONE, + }, ++ { ++ .vendor = "NVME", ++ .product = "^EMC PowerMax_", ++ .uid_attribute = "ID_WWN", ++ .pgpolicy = MULTIBUS, ++ .checker_name = NONE, ++ .prio_name = DEFAULT_PRIO, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0268-RHBZ-1721855-mpathpersist-fixes.patch b/SOURCES/0268-RHBZ-1721855-mpathpersist-fixes.patch new file mode 100644 index 0000000..d4d06ad --- /dev/null +++ b/SOURCES/0268-RHBZ-1721855-mpathpersist-fixes.patch @@ -0,0 +1,136 @@ +--- + libmpathpersist/mpath_persist.c | 2 +- + mpathpersist/main.c | 36 ++++++++++++++++++++++-------------- + 2 files changed, 23 insertions(+), 15 deletions(-) + +Index: multipath-tools-130222/mpathpersist/main.c +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.c ++++ multipath-tools-130222/mpathpersist/main.c +@@ -141,7 +141,8 @@ static int do_batch_file(const char *bat + + static int handle_args(int argc, char * argv[], int nline) + { +- int fd, c; ++ int c; ++ int fd = -1; + const char *device_name = NULL; + int num_prin_sa = 0; + int num_prout_sa = 0; +@@ -199,7 +200,8 @@ static int handle_args(int argc, char * + if (nline == 0 && 1 != sscanf (optarg, "%d", &loglevel)) + { + fprintf (stderr, "bad argument to '--verbose'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + break; + +@@ -214,6 +216,7 @@ static int handle_args(int argc, char * + + case 'h': + usage (); ++ free(batch_fn); + return 0; + + case 'H': +@@ -236,7 +239,8 @@ static int handle_args(int argc, char * + if (parse_prkey(optarg, ¶m_rk) != 0) + { + fprintf (stderr, "bad argument to '--param-rk'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + ++num_prout_param; + break; +@@ -245,7 +249,8 @@ static int handle_args(int argc, char * + if (parse_prkey(optarg, ¶m_sark) != 0) + { + fprintf (stderr, "bad argument to '--param-sark'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + ++num_prout_param; + break; +@@ -264,7 +269,8 @@ static int handle_args(int argc, char * + if (1 != sscanf (optarg, "%x", &prout_type)) + { + fprintf (stderr, "bad argument to '--prout-type'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + ++num_prout_param; + break; +@@ -312,7 +318,8 @@ static int handle_args(int argc, char * + case 'X': + if (0 != construct_transportid(optarg, transportids, num_transport)) { + fprintf(stderr, "bad argument to '--transport-id'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + + ++num_transport; +@@ -320,12 +327,13 @@ static int handle_args(int argc, char * + + case 'l': + if (1 != sscanf(optarg, "%u", &mpath_mx_alloc_len)) { +- fprintf(stderr, "bad argument to '--alloc-length'\n"); +- return MPATH_PR_SYNTAX_ERROR; ++ fprintf(stderr, "bad argument to '--alloc-length'\n"); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } else if (MPATH_MAX_PARAM_LEN < mpath_mx_alloc_len) { +- fprintf(stderr, "'--alloc-length' argument exceeds maximum" +- " limit(%d)\n", MPATH_MAX_PARAM_LEN); +- return MPATH_PR_SYNTAX_ERROR; ++ fprintf(stderr, "'--alloc-length' argument exceeds maximum limit(%d)\n", MPATH_MAX_PARAM_LEN); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out; + } + break; + +@@ -465,14 +473,14 @@ static int handle_args(int argc, char * + { + fprintf (stderr, "failed to allocate PRIN response buffer\n"); + ret = MPATH_PR_OTHER; +- goto out; ++ goto out_fd; + } + + ret = __mpath_persistent_reserve_in (fd, prin_sa, resp, noisy); + if (ret != MPATH_PR_SUCCESS ) + { + fprintf (stderr, "Persistent Reserve IN command failed\n"); +- goto out; ++ goto out_fd; + } + + switch(prin_sa) +@@ -552,8 +560,8 @@ static int handle_args(int argc, char * + printf("PR out: command failed\n"); + } + ++out_fd: + close (fd); +- + out : + if (ret == MPATH_PR_SYNTAX_ERROR) { + free(batch_fn); +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -585,7 +585,7 @@ int mpath_prout_common(struct multipath + return ret ; + } + } +- return MPATH_PR_SUCCESS; ++ return MPATH_PR_DMMP_ERROR; + } + + int send_prout_activepath(char * dev, int rq_servact, int rq_scope, diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 918bddb..02245ff 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: 127%{?dist} +Release: 131%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -265,6 +265,16 @@ Patch0255: 0255-RHBZ-1638651-marginal-path.patch Patch0256: 0256-RHBZ-1672175-retry-no-fd-paths.patch Patch0257: 0257-RHBZ-1679556-dont-check-dm-devices.patch Patch0258: 0258-RHBZ-1634183-ANA-prioritizer.patch +Patch0259: 0259-RHBZ-1701604-fix-nr-active.patch +Patch0260: 0260-RHBZ-1634183-prio-fixes.patch +#Patch0261: 0261-RHBZ-1714506-skip-blacklisted-paths.patch +Patch0262: 0262-RHBZ-1699486-reload-with-failed-paths.patch +Patch0263: 0263-RHBZ-1686708-nvme-hcil.patch +Patch0264: 0264-RHBZ-1699441-de-series-config.patch +Patch0265: 0265-RHBZ-1721855-mpathpersist-speedup.patch +Patch0266: 0266-RHBZ-1696817-fix-emc-checker.patch +Patch0267: 0267-RHBZ-1661156-powermax-config.patch +Patch0268: 0268-RHBZ-1721855-mpathpersist-fixes.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -610,6 +620,16 @@ device-mapper-multipath's libdmmp C API library %patch0256 -p1 %patch0257 -p1 %patch0258 -p1 +%patch0259 -p1 +%patch0260 -p1 +# %patch0261 -p1 +%patch0262 -p1 +%patch0263 -p1 +%patch0264 -p1 +%patch0265 -p1 +%patch0266 -p1 +%patch0267 -p1 +%patch0268 -p1 cp %{SOURCE1} . %build @@ -727,6 +747,41 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Tue Dec 10 2019 Benjamin Marzinski 0.4.9-131 +- Modify 0268-RHBZ-1721855-mpathpersist-fixes.patch + * The fix for 1721855 broke 1714506. +- Resolves: bz #1714506 + +* Fri Aug 30 2019 Benjamin Marzinski 0.4.9-130 +- Add 0268-RHBZ-1721855-mpathpersist-fixes.patch + * Fix issues in the mpathpersist speedup code +- Resolves: bz #1721855 + +* Thu Aug 29 2019 Benjamin Marzinski 0.4.9-129 +- Add 0265-RHBZ-1721855-mpathpersist-speedup.patch + * only grab path information from necessary devices, and allow batch files. +- Add 0266-RHBZ-1696817-fix-emc-checker.patch + * fix detection of inactive snapshots +- Add 0267-RHBZ-1661156-powermax-config.patch +- Remove 0261-RHBZ-1714506-skip-blacklisted-paths.patch + * This fix is superseded by 0265-RHBZ-1721855-mpathpersist-speedup.patch +- Resolves: bz #1661156, #1696817, #1721855 + +* Mon Aug 12 2019 Benjamin Marzinski 0.4.9-128 +- Modify 0258-RHBZ-1634183-ANA-prioritizer.patch + * minor change +- Add 0259-RHBZ-1701604-fix-nr-active.patch + * recalculate the number of active paths whenever a path is checked +- Add 0260-RHBZ-1634183-prio-fixes.patch +- Add 0261-RHBZ-1714506-skip-blacklisted-paths.patch + * ignore blacklisted paths in mpathpersist +- Add 0262-RHBZ-1699486-reload-with-failed-paths.patch + * allow forced reloads even if there are no reusable paths +- Add 0263-RHBZ-1686708-nvme-hcil.patch + * make nvme ids work like in upstream +- Add 0264-RHBZ-1699441-de-series-config.patch +- Resolves: bz #1686708, #1699441, #1699486, #1701604, #1714506 + * Thu Mar 14 2019 Benjamin Marzinski 0.4.9-127 - Add 0256-RHBZ-1672175-retry-no-fd-paths.patch * retry adding paths if they couldn't be opened initially