--- 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