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