f20720
---
f20720
 libmpathpersist/mpath_persist.c  |   79 +++++++++---------
f20720
 libmpathpersist/mpath_updatepr.c |   40 +++++----
f20720
 libmpathpersist/mpathpr.h        |    5 -
f20720
 libmultipath/Makefile            |    2 
f20720
 libmultipath/byteorder.h         |   43 ++++++++++
f20720
 libmultipath/checkers/rbd.c      |   16 ---
f20720
 libmultipath/config.c            |    9 +-
f20720
 libmultipath/config.h            |    9 +-
f20720
 libmultipath/defaults.h          |    1 
f20720
 libmultipath/dict.c              |  140 ++++++++++++--------------------
f20720
 libmultipath/prkey.c             |  167 +++++++++++++++++++++++++++++++++++++++
f20720
 libmultipath/prkey.h             |   19 ++++
f20720
 libmultipath/propsel.c           |   58 ++++++-------
f20720
 libmultipath/structs.h           |   14 ++-
f20720
 libmultipath/util.c              |   34 +++++++
f20720
 libmultipath/util.h              |    4 
f20720
 mpathpersist/main.c              |    5 -
f20720
 multipath/multipath.conf.5       |   18 +++-
f20720
 multipathd/cli.c                 |    7 +
f20720
 multipathd/cli.h                 |    8 +
f20720
 multipathd/cli_handlers.c        |   69 ++++++++++++++++
f20720
 multipathd/cli_handlers.h        |    4 
f20720
 multipathd/main.c                |   29 ++----
f20720
 multipathd/multipathd.8          |   13 +++
f20720
 24 files changed, 576 insertions(+), 217 deletions(-)
f20720
526b4e
Index: multipath-tools-130222/libmpathpersist/mpath_persist.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c
526b4e
+++ multipath-tools-130222/libmpathpersist/mpath_persist.c
f20720
@@ -221,9 +221,7 @@ int mpath_persistent_reserve_out ( int f
f20720
 	int map_present;
f20720
 	int major, minor;
f20720
 	int ret;
f20720
-	int j;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey;		
f20720
+	uint64_t prkey;
f20720
 
f20720
 	conf->verbosity = verbose;
f20720
 
f20720
@@ -290,6 +288,27 @@ int mpath_persistent_reserve_out ( int f
f20720
 
f20720
 	select_reservation_key(mpp);
f20720
 
f20720
+	memcpy(&prkey, paramp->sa_key, 8);
f20720
+	if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
f20720
+	    ((!get_be64(mpp->reservation_key) &&
f20720
+	      rq_servact == MPATH_PROUT_REG_SA) ||
f20720
+	     rq_servact == MPATH_PROUT_REG_IGN_SA)) {
f20720
+		memcpy(&mpp->reservation_key, paramp->sa_key, 8);
f20720
+		if (update_prkey(alias, get_be64(mpp->reservation_key))) {
f20720
+			condlog(0, "%s: failed to set prkey for multipathd.",
f20720
+				alias);
f20720
+			ret = MPATH_PR_DMMP_ERROR;
f20720
+			goto out1;
f20720
+		}
f20720
+	}
f20720
+
f20720
+	if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
f20720
+	    memcmp(paramp->sa_key, &mpp->reservation_key, 8)) {
f20720
+		condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
f20720
+		ret = MPATH_PR_SYNTAX_ERROR;
f20720
+		goto out1;
f20720
+	}
f20720
+
f20720
 	switch(rq_servact)
f20720
 	{
f20720
 		case MPATH_PROUT_REG_SA: 
f20720
@@ -311,24 +330,19 @@ int mpath_persistent_reserve_out ( int f
f20720
 	}
f20720
 
f20720
 	if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
f20720
-				(rq_servact ==  MPATH_PROUT_REG_IGN_SA)))
f20720
+				(rq_servact == MPATH_PROUT_REG_IGN_SA)))
f20720
 	{
f20720
-		keyp=paramp->sa_key;
f20720
-		prkey = 0;
f20720
-		for (j = 0; j < 8; ++j) {
f20720
-			if (j > 0)
f20720
-				prkey <<= 8;
f20720
-			prkey |= *keyp;
f20720
-			++keyp;
f20720
+		if (!prkey) {
f20720
+			update_prflag(alias, 0);
f20720
+			update_prkey(alias, 0);
f20720
 		}
f20720
-		if (prkey == 0)
f20720
-			update_prflag(alias, "unset", noisy);
f20720
 		else
f20720
-			update_prflag(alias, "set", noisy);
f20720
+			update_prflag(alias, 1);
f20720
 	} else {
f20720
-		if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_CLEAR_SA) || 
f20720
-					(rq_servact == MPATH_PROUT_PREE_AB_SA ))){
f20720
-			update_prflag(alias, "unset", noisy);
f20720
+		if ((ret == MPATH_PR_SUCCESS) &&
f20720
+		    (rq_servact == MPATH_PROUT_CLEAR_SA)) {
f20720
+			update_prflag(alias, 0);
f20720
+			update_prkey(alias, 0);
f20720
 		}
f20720
 	}
f20720
 out1:
f20720
@@ -729,8 +743,8 @@ int mpath_prout_rel(struct multipath *mp
f20720
 		goto out1;
f20720
 	}
f20720
 
f20720
-	if (mpp->reservation_key ){
f20720
-		memcpy (pamp->key, mpp->reservation_key, 8);
f20720
+	if (get_be64(mpp->reservation_key)){
f20720
+		memcpy (pamp->key, &mpp->reservation_key, 8);
f20720
 		condlog (3, "%s: reservation key set.", mpp->wwid);
f20720
 	}
f20720
 
f20720
@@ -741,9 +755,9 @@ int mpath_prout_rel(struct multipath *mp
f20720
 	pptr=pamp->trnptid_list[0];
f20720
 
f20720
 	for (i = 0; i < num; i++){
f20720
-		if (mpp->reservation_key && 
f20720
+		if (get_be64(mpp->reservation_key) &&
f20720
 			memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
f20720
-			mpp->reservation_key, 8)){	
f20720
+			&mpp->reservation_key, 8)){
f20720
 			/*register with tarnsport id*/
f20720
 			memset(pamp, 0, length);
f20720
 			pamp->trnptid_list[0] = pptr;
f20720
@@ -768,7 +782,7 @@ int mpath_prout_rel(struct multipath *mp
f20720
 		}
f20720
 		else
f20720
 		{
f20720
-			if (mpp->reservation_key)
f20720
+			if (get_be64(mpp->reservation_key))
f20720
 				found = 1;
f20720
 		}
f20720
 
f20720
@@ -777,7 +791,7 @@ int mpath_prout_rel(struct multipath *mp
f20720
 
f20720
 	if (found){
f20720
 		memset (pamp, 0, length);
f20720
-		memcpy (pamp->sa_key, mpp->reservation_key, 8);
f20720
+		memcpy (pamp->sa_key, &mpp->reservation_key, 8);
f20720
 		memset (pamp->key, 0, 8);
f20720
 		status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);	
f20720
 	}
f20720
@@ -826,11 +840,9 @@ int update_map_pr(struct multipath *mpp)
f20720
 {
f20720
 	int noisy=0;
f20720
 	struct prin_resp *resp;
f20720
-	int i,j, ret, isFound;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey;
f20720
+	int i, ret, isFound;
f20720
 
f20720
-	if (!mpp->reservation_key)
f20720
+	if (!get_be64(mpp->reservation_key))
f20720
 	{
f20720
 		/* Nothing to do. Assuming pr mgmt feature is disabled*/
f20720
 		condlog(3, "%s: reservation_key not set in multipath.conf", mpp->alias);
f20720
@@ -859,15 +871,8 @@ int update_map_pr(struct multipath *mpp)
f20720
 		return MPATH_PR_SUCCESS;
f20720
 	}
f20720
 
f20720
-	prkey = 0;
f20720
-	keyp = mpp->reservation_key;
f20720
-	for (j = 0; j < 8; ++j) {
f20720
-		if (j > 0)
f20720
-			prkey <<= 8;
f20720
-		prkey |= *keyp;
f20720
-		++keyp;
f20720
-	}
f20720
-	condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias, prkey);
f20720
+	condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias,
f20720
+		get_be64(mpp->reservation_key));
f20720
 
f20720
 	isFound =0;
f20720
 	for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
f20720
@@ -875,7 +880,7 @@ int update_map_pr(struct multipath *mpp)
f20720
 		condlog(2, "%s: PR IN READKEYS[%d]  reservation key:", mpp->alias, i);
f20720
 		dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
f20720
 
f20720
-		if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
f20720
+		if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
f20720
 		{
f20720
 			condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
f20720
 			isFound =1;
526b4e
Index: multipath-tools-130222/libmpathpersist/mpath_updatepr.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmpathpersist/mpath_updatepr.c
526b4e
+++ multipath-tools-130222/libmpathpersist/mpath_updatepr.c
f20720
@@ -1,7 +1,7 @@
f20720
-#include<stdio.h>
f20720
-#include<unistd.h>
f20720
+#include <stdio.h>
f20720
+#include <unistd.h>
f20720
 #include <errno.h>
f20720
-
f20720
+#include <inttypes.h>
f20720
 #include <stdlib.h>
f20720
 #include <stdarg.h>
f20720
 #include <fcntl.h>
f20720
@@ -18,10 +18,10 @@
f20720
 
f20720
 unsigned long mem_allocated;    /* Total memory used in Bytes */
f20720
 
f20720
-int update_prflag(char * arg1, char * arg2, int noisy)
f20720
+static int do_update_pr(char * mapname, char * arg)
f20720
 {
f20720
 	int fd;
f20720
-	char str[64];
f20720
+	char str[256];
f20720
 	char *reply;
f20720
 	int ret = 0;
f20720
 
f20720
@@ -31,25 +31,35 @@ int update_prflag(char * arg1, char * ar
f20720
 		return 1 ;
f20720
 	}
f20720
 
f20720
-	snprintf(str,sizeof(str),"map %s %s", arg1, arg2);
f20720
-	condlog (2, "%s: pr flag message=%s", arg1, str);
f20720
+	snprintf(str,sizeof(str),"map %s %s", mapname, arg);
f20720
+	condlog (2, "%s: pr message=%s", mapname, arg);
f20720
 	send_packet(fd, str);
f20720
 	ret = recv_packet(fd, &reply);
f20720
 	if (ret < 0) {
f20720
-		condlog(2, "%s: message=%s recv error=%d", arg1, str, errno);
f20720
+		condlog(2, "%s: message=%s recv error=%d", mapname, str, errno);
f20720
 		ret = -2;
f20720
 	} else {
f20720
-		condlog (2, "%s: message=%s reply=%s", arg1, str, reply);
f20720
+		condlog (2, "%s: message=%s reply=%s", mapname, str, reply);
f20720
 		if (!reply || strncmp(reply,"ok", 2) == 0)
f20720
-			ret = -1;
f20720
-		else if (strncmp(reply, "fail", 4) == 0)
f20720
-			ret = -2;
f20720
-		else{
f20720
-			ret = atoi(reply);
f20720
-		}
f20720
+			ret = 0;
f20720
+		else ret = -1;
f20720
 	}
f20720
 
f20720
 	free(reply);
f20720
 	mpath_disconnect(fd);
f20720
 	return ret;
f20720
 }
f20720
+
f20720
+int update_prflag(char *mapname, int set) {
f20720
+	return do_update_pr(mapname, (set)? "setprstatus" : "unsetprstatus");
f20720
+}
f20720
+
f20720
+int update_prkey(char *mapname, uint64_t prkey) {
f20720
+	char str[256];
f20720
+
f20720
+	if (prkey)
f20720
+		snprintf(str, sizeof(str), "setprkey key %" PRIx64, prkey);
f20720
+	else
f20720
+		snprintf(str, sizeof(str), "unsetprkey");
f20720
+	return do_update_pr(mapname, str);
f20720
+}
526b4e
Index: multipath-tools-130222/libmpathpersist/mpathpr.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmpathpersist/mpathpr.h
526b4e
+++ multipath-tools-130222/libmpathpersist/mpathpr.h
f20720
@@ -1,6 +1,8 @@
f20720
 #ifndef MPATHPR_H
f20720
 #define MPATHPR_H
f20720
 
f20720
+#include <inttypes.h>
f20720
+
f20720
 struct prin_param {
f20720
 	char dev[FILE_NAME_SIZE];
f20720
         int rq_servact;
f20720
@@ -47,7 +49,8 @@ int mpath_prout_rel(struct multipath *mp
f20720
 int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
f20720
         unsigned int rq_type,   struct prout_param_descriptor * paramp, int noisy);
f20720
 
f20720
-int update_prflag(char * arg1, char * arg2, int noisy);
f20720
+int update_prflag(char *mapname, int set);
f20720
+int update_prkey(char *mapname, uint64_t prkey);
f20720
 void * mpath_alloc_prin_response(int prin_sa);
f20720
 int update_map_pr(struct multipath *mpp);
f20720
 int devt2devname (char *devname, char *devt);
526b4e
Index: multipath-tools-130222/libmultipath/byteorder.h
f20720
===================================================================
f20720
--- /dev/null
526b4e
+++ multipath-tools-130222/libmultipath/byteorder.h
f20720
@@ -0,0 +1,43 @@
f20720
+#ifndef BYTEORDER_H_INCLUDED
f20720
+#define BYTEORDER_H_INCLUDED
f20720
+
f20720
+#ifdef __linux__
f20720
+#  include <endian.h>
f20720
+#  include <byteswap.h>
f20720
+#else
f20720
+#  error unsupported
f20720
+#endif
f20720
+
f20720
+#if BYTE_ORDER == LITTLE_ENDIAN
f20720
+#  define le16_to_cpu(x) (x)
f20720
+#  define be16_to_cpu(x) bswap_16(x)
f20720
+#  define le32_to_cpu(x) (x)
f20720
+#  define le64_to_cpu(x) (x)
f20720
+#  define be32_to_cpu(x) bswap_32(x)
f20720
+#  define be64_to_cpu(x) bswap_64(x)
f20720
+#elif BYTE_ORDER == BIG_ENDIAN
f20720
+#  define le16_to_cpu(x) bswap_16(x)
f20720
+#  define be16_to_cpu(x) (x)
f20720
+#  define le32_to_cpu(x) bswap_32(x)
f20720
+#  define le64_to_cpu(x) bswap_64(x)
f20720
+#  define be32_to_cpu(x) (x)
f20720
+#  define be64_to_cpu(x) (x)
f20720
+#else
f20720
+#  error unsupported
f20720
+#endif
f20720
+
f20720
+#define cpu_to_le16(x) le16_to_cpu(x)
f20720
+#define cpu_to_be16(x) be16_to_cpu(x)
f20720
+#define cpu_to_le32(x) le32_to_cpu(x)
f20720
+#define cpu_to_be32(x) be32_to_cpu(x)
f20720
+#define cpu_to_le64(x) le64_to_cpu(x)
f20720
+#define cpu_to_be64(x) be64_to_cpu(x)
f20720
+
f20720
+struct be64 {
f20720
+        uint64_t _v;
f20720
+};
f20720
+
f20720
+#define get_be64(x) be64_to_cpu((x)._v)
f20720
+#define put_be64(x, y) do { (x)._v = cpu_to_be64(y); } while (0)
f20720
+
f20720
+#endif				/* BYTEORDER_H_INCLUDED */
526b4e
Index: multipath-tools-130222/libmultipath/checkers/rbd.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/checkers/rbd.c
526b4e
+++ multipath-tools-130222/libmultipath/checkers/rbd.c
f20720
@@ -27,6 +27,7 @@
f20720
 
f20720
 #include "../libmultipath/debug.h"
f20720
 #include "../libmultipath/uevent.h"
f20720
+#include "../libmultipath/util.h"
f20720
 
f20720
 struct rbd_checker_context;
f20720
 typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg);
f20720
@@ -355,21 +356,6 @@ int rbd_check(struct rbd_checker_context
f20720
 	return PATH_UP;
f20720
 }
f20720
 
f20720
-int safe_write(int fd, const void *buf, size_t count)
f20720
-{
f20720
-	while (count > 0) {
f20720
-		ssize_t r = write(fd, buf, count);
f20720
-		if (r < 0) {
f20720
-			if (errno == EINTR)
f20720
-				continue;
f20720
-			return -errno;
f20720
-		}
f20720
-		count -= r;
f20720
-		buf = (char *)buf + r;
f20720
-	}
f20720
-	return 0;
f20720
-}
f20720
-
f20720
 static int sysfs_write_rbd_bus(const char *which, const char *buf,
f20720
 			       size_t buf_len)
f20720
 {
526b4e
Index: multipath-tools-130222/libmultipath/config.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/config.c
526b4e
+++ multipath-tools-130222/libmultipath/config.c
f20720
@@ -574,6 +574,9 @@ free_config (struct config * conf)
f20720
 	if (conf->wwids_file)
f20720
 		FREE(conf->wwids_file);
f20720
 
f20720
+	if (conf->prkeys_file)
f20720
+		FREE(conf->prkeys_file);
f20720
+
f20720
 	if (conf->prio_name)
f20720
 		FREE(conf->prio_name);
f20720
 
f20720
@@ -589,9 +592,6 @@ free_config (struct config * conf)
f20720
 	if (conf->config_dir)
f20720
 		FREE(conf->config_dir);
f20720
 
f20720
-	if (conf->reservation_key)
f20720
-		FREE(conf->reservation_key);
f20720
-
f20720
 	free_blacklist(conf->blist_devnode);
f20720
 	free_blacklist(conf->blist_wwid);
f20720
 	free_blacklist_device(conf->blist_device);
f20720
@@ -666,6 +666,7 @@ load_config (char * file, struct udev *u
f20720
 	get_sys_max_fds(&conf->max_fds);
f20720
 	conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
f20720
 	conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
f20720
+	conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
f20720
 	conf->bindings_read_only = 0;
f20720
 	conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
f20720
 	conf->features = set_default(DEFAULT_FEATURES);
f20720
@@ -806,7 +807,7 @@ load_config (char * file, struct udev *u
f20720
 		conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
f20720
 
f20720
 	if (!conf->multipath_dir || !conf->bindings_file ||
f20720
-	    !conf->wwids_file)
f20720
+	    !conf->wwids_file || !conf->prkeys_file)
f20720
 		goto out;
f20720
 
f20720
 	if (conf->ignore_new_boot_devs)
526b4e
Index: multipath-tools-130222/libmultipath/config.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/config.h
526b4e
+++ multipath-tools-130222/libmultipath/config.h
f20720
@@ -3,6 +3,8 @@
f20720
 
f20720
 #include <sys/types.h>
f20720
 #include <stdint.h>
f20720
+#include <inttypes.h>
f20720
+#include "byteorder.h"
f20720
 
f20720
 #define ORIGIN_DEFAULT 0
f20720
 #define ORIGIN_CONFIG  1
f20720
@@ -80,7 +82,8 @@ struct mpentry {
f20720
 
f20720
 	char * prio_name;
f20720
 	char * prio_args;
f20720
-	unsigned char * reservation_key;
f20720
+	int prkey_source;
f20720
+	struct be64 reservation_key;
f20720
 	int pgpolicy;
f20720
 	int pgfailback;
f20720
 	int rr_weight;
f20720
@@ -167,12 +170,14 @@ struct config {
f20720
 	char * hwhandler;
f20720
 	char * bindings_file;
f20720
 	char * wwids_file;
f20720
+	char * prkeys_file;
f20720
 	char * prio_name;
f20720
 	char * prio_args;
f20720
 	char * checker_name;
f20720
 	char * alias_prefix;
f20720
 	char * config_dir;
f20720
-	unsigned char * reservation_key;
f20720
+	int prkey_source;
f20720
+	struct be64 reservation_key;
f20720
 
f20720
 	vector keywords;
f20720
 	vector mptable;
526b4e
Index: multipath-tools-130222/libmultipath/defaults.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/defaults.h
526b4e
+++ multipath-tools-130222/libmultipath/defaults.h
f20720
@@ -39,6 +39,7 @@
f20720
 #define DEFAULT_CONFIGFILE	"/etc/multipath.conf"
f20720
 #define DEFAULT_BINDINGS_FILE	"/etc/multipath/bindings"
f20720
 #define DEFAULT_WWIDS_FILE	"/etc/multipath/wwids"
f20720
+#define DEFAULT_PRKEYS_FILE	"/etc/multipath/prkeys"
f20720
 #define DEFAULT_CONFIG_DIR	"/etc/multipath/conf.d"
f20720
 
f20720
 char * set_default (char * str);
526b4e
Index: multipath-tools-130222/libmultipath/dict.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/dict.c
526b4e
+++ multipath-tools-130222/libmultipath/dict.c
f20720
@@ -20,6 +20,8 @@
f20720
 #include "defaults.h"
f20720
 #include "prio.h"
f20720
 #include "errno.h"
f20720
+#include "util.h"
f20720
+#include "prkey.h"
f20720
 #include <inttypes.h>
f20720
 
f20720
 /*
f20720
@@ -554,46 +556,26 @@ static int
f20720
 def_reservation_key_handler(vector strvec)
f20720
 {
f20720
 	char *buff;
f20720
-	char *tbuff;
f20720
-	int j, k;
f20720
-	int len;
f20720
-	uint64_t prkey;
f20720
+	uint64_t prkey = 0;
f20720
 
f20720
 	buff = set_value(strvec);
f20720
 	if (!buff)
f20720
 		return 1;
f20720
 
f20720
-	tbuff = buff;
f20720
-
f20720
-	if (!memcmp("0x",buff, 2))
f20720
-		buff = buff + 2;
f20720
-
f20720
-	len = strlen(buff);
f20720
-
f20720
-	k = strspn(buff, "0123456789aAbBcCdDeEfF");
f20720
-
f20720
-	if (len != k) {
f20720
-		FREE(tbuff);
f20720
-		return 1;
f20720
+	if (strlen(buff) == 4 && !strcmp(buff, "file")) {
f20720
+		conf->prkey_source = PRKEY_SOURCE_FILE;
f20720
+		put_be64(conf->reservation_key, 0);
f20720
+		FREE(buff);
f20720
+		return 0;
f20720
 	}
f20720
-
f20720
-	if (1 != sscanf (buff, "%" SCNx64 "", &prkey))
f20720
-	{
f20720
-		FREE(tbuff);
f20720
+	else if (parse_prkey(buff, &prkey) != 0) {
f20720
+		FREE(buff);
f20720
 		return 1;
f20720
 	}
f20720
 
f20720
-	if (!conf->reservation_key)
f20720
-		conf->reservation_key = (unsigned char *) malloc(8);
f20720
-
f20720
-	memset(conf->reservation_key, 0, 8);
f20720
-
f20720
-	for (j = 7; j >= 0; --j) {
f20720
-		conf->reservation_key[j] = (prkey & 0xff);
f20720
-		prkey >>= 8;
f20720
-	}
f20720
-
f20720
-	FREE(tbuff);
f20720
+	conf->prkey_source = PRKEY_SOURCE_CONF;
f20720
+	put_be64(conf->reservation_key, prkey);
f20720
+	FREE(buff);
f20720
 	return 0;
f20720
 }
f20720
 
f20720
@@ -668,6 +650,19 @@ wwids_file_handler(vector strvec)
f20720
 }
f20720
 
f20720
 static int
f20720
+prkeys_file_handler(vector strvec)
f20720
+{
f20720
+	if (conf->prkeys_file)
f20720
+		FREE(conf->prkeys_file);
f20720
+	conf->prkeys_file = set_value(strvec);
f20720
+
f20720
+	if (!conf->prkeys_file)
f20720
+		return 1;
f20720
+
f20720
+	return 0;
f20720
+}
f20720
+
f20720
+static int
f20720
 def_retain_hwhandler_handler(vector strvec)
f20720
 {
f20720
 	char * buff;
f20720
@@ -2282,10 +2277,7 @@ static int
f20720
 mp_reservation_key_handler (vector strvec)
f20720
 {
f20720
 	char *buff;
f20720
-	char *tbuff;
f20720
 	struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
f20720
-
f20720
-	int j, k, len;
f20720
 	uint64_t prkey;
f20720
 
f20720
 	if (!mpe)
f20720
@@ -2295,35 +2287,20 @@ mp_reservation_key_handler (vector strve
f20720
 	if (!buff)
f20720
 		return 1;
f20720
 
f20720
-	tbuff = buff;
f20720
-	if (!memcmp(buff, "0x", 2))
f20720
-		buff = buff + 2;
f20720
-
f20720
-	len = strlen(buff);
f20720
-
f20720
-	k = strspn(buff, "0123456789aAbBcCdDeEfF");
f20720
-	if (len != k) {
f20720
-		FREE(tbuff);
f20720
-		return 1;
f20720
+	if (strlen(buff) == 4 && !strcmp(buff, "file")) {
f20720
+		mpe->prkey_source = PRKEY_SOURCE_FILE;
f20720
+		put_be64(mpe->reservation_key, 0);
f20720
+		FREE(buff);
f20720
+		return 0;
f20720
 	}
f20720
-
f20720
-	if (1 != sscanf (buff, "%" SCNx64 "", &prkey))
f20720
-	{
f20720
-		FREE(tbuff);
f20720
+	else if (parse_prkey(buff, &prkey) != 0) {
f20720
+		FREE(buff);
f20720
 		return 1;
f20720
 	}
f20720
 
f20720
-	if (!mpe->reservation_key)
f20720
-		mpe->reservation_key = (unsigned char *) malloc(8);
f20720
-
f20720
-	memset(mpe->reservation_key, 0, 8);
f20720
-
f20720
-	for (j = 7; j >= 0; --j) {
f20720
-		mpe->reservation_key[j] = (prkey & 0xff);
f20720
-		prkey >>= 8;
f20720
-	}
f20720
-
f20720
-	FREE(tbuff);
f20720
+	mpe->prkey_source = PRKEY_SOURCE_CONF;
f20720
+	put_be64(mpe->reservation_key, prkey);
f20720
+	FREE(buff);
f20720
 	return 0;
f20720
 }
f20720
 
f20720
@@ -2714,22 +2691,14 @@ snprint_mp_prio_args(char * buff, int le
f20720
 static int
f20720
 snprint_mp_reservation_key (char * buff, int len, void * data)
f20720
 {
f20720
-	int i;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey = 0;
f20720
 	struct mpentry * mpe = (struct mpentry *)data;
f20720
 
f20720
-	if (!mpe->reservation_key)
f20720
+	if (mpe->prkey_source == PRKEY_SOURCE_NONE)
f20720
 		return 0;
f20720
-	keyp = (unsigned char *)mpe->reservation_key;
f20720
-	for (i = 0; i < 8; i++) {
f20720
-		if (i > 0)
f20720
-			prkey <<= 8;
f20720
-		prkey |= *keyp;
f20720
-		keyp++;
f20720
-	}
f20720
-
f20720
-	return snprintf(buff, len, "0x%" PRIx64, prkey);
f20720
+	if (mpe->prkey_source == PRKEY_SOURCE_FILE)
f20720
+		return snprintf(buff, len, "file");
f20720
+	return snprintf(buff, len, "0x%" PRIx64,
f20720
+			get_be64(mpe->reservation_key));
f20720
 }
f20720
 
f20720
 static int
f20720
@@ -3551,22 +3520,22 @@ snprint_def_wwids_file (char * buff, int
f20720
 }
f20720
 
f20720
 static int
f20720
-snprint_def_reservation_key(char * buff, int len, void * data)
f20720
+snprint_def_prkeys_file (char * buff, int len, void * data)
f20720
 {
f20720
-	int i;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey = 0;
f20720
+	if (conf->prkeys_file == NULL)
f20720
+		return 0;
f20720
+	return snprintf(buff, len, "%s", conf->prkeys_file);
f20720
+}
f20720
 
f20720
-	if (!conf->reservation_key)
f20720
+static int
f20720
+snprint_def_reservation_key(char * buff, int len, void * data)
f20720
+{
f20720
+	if (conf->prkey_source == PRKEY_SOURCE_NONE)
f20720
 		return 0;
f20720
-	keyp = (unsigned char *)conf->reservation_key;
f20720
-	for (i = 0; i < 8; i++) {
f20720
-		if (i > 0)
f20720
-			prkey <<= 8;
f20720
-		prkey |= *keyp;
f20720
-		keyp++;
f20720
-	}
f20720
-	return snprintf(buff, len, "0x%" PRIx64, prkey);
f20720
+	if (conf->prkey_source == PRKEY_SOURCE_FILE)
f20720
+		return snprintf(buff, len, "file");
f20720
+	return snprintf(buff, len, "0x%" PRIx64,
f20720
+			get_be64(conf->reservation_key));
f20720
 }
f20720
 
f20720
 static int
f20720
@@ -3788,6 +3757,7 @@ init_keywords(void)
f20720
 	install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
f20720
 	install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file);
f20720
 	install_keyword("wwids_file", &wwids_file_handler, &snprint_def_wwids_file);
f20720
+	install_keyword("prkeys_file", &prkeys_file_handler, &snprint_def_prkeys_file);
f20720
 	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
f20720
 	install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key);
f20720
 	install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
526b4e
Index: multipath-tools-130222/libmultipath/prkey.c
f20720
===================================================================
f20720
--- /dev/null
526b4e
+++ multipath-tools-130222/libmultipath/prkey.c
f20720
@@ -0,0 +1,167 @@
f20720
+#include "prkey.h"
f20720
+#include "structs.h"
f20720
+#include "file.h"
f20720
+#include "debug.h"
f20720
+#include "config.h"
f20720
+#include "util.h"
f20720
+#include "propsel.h"
f20720
+#include <sys/types.h>
f20720
+#include <unistd.h>
f20720
+#include <stdio.h>
f20720
+#include <string.h>
f20720
+#include <inttypes.h>
f20720
+#include <errno.h>
f20720
+
f20720
+#define KEYSIZE 19
f20720
+#define PRKEY_READ 0
f20720
+#define PRKEY_WRITE 1
f20720
+
f20720
+static int do_prkey(int fd, char *wwid, char *keystr, int cmd)
f20720
+{
f20720
+	char buf[4097];
f20720
+	char *ptr;
f20720
+	off_t start = 0;
f20720
+	int bytes;
f20720
+
f20720
+	while (1) {
f20720
+		if (lseek(fd, start, SEEK_SET) < 0) {
f20720
+			condlog(0, "prkey file read lseek failed : %s",
f20720
+				strerror(errno));
f20720
+			return 1;
f20720
+		}
f20720
+		bytes = read(fd, buf, 4096);
f20720
+		if (bytes < 0) {
f20720
+			if (errno == EINTR || errno == EAGAIN)
f20720
+				continue;
f20720
+			condlog(0, "failed to read from prkey file : %s",
f20720
+				strerror(errno));
f20720
+			return 1;
f20720
+		}
f20720
+		if (!bytes) {
f20720
+			ptr = NULL;
f20720
+			break;
f20720
+		}
f20720
+		buf[bytes] = '\0';
f20720
+		ptr = strstr(buf, wwid);
f20720
+		while (ptr) {
f20720
+			if (ptr == buf || *(ptr - 1) != ' ' ||
f20720
+			    *(ptr + strlen(wwid)) != '\n')
f20720
+				ptr = strstr(ptr + strlen(wwid), wwid);
f20720
+			else
f20720
+				break;
f20720
+		}
f20720
+		if (ptr) {
f20720
+			condlog(3, "found prkey for '%s'", wwid);
f20720
+			ptr[strlen(wwid)] = '\0';
f20720
+			if (ptr - KEYSIZE < buf ||
f20720
+			    (ptr - KEYSIZE != buf &&
f20720
+			     *(ptr - KEYSIZE - 1) != '\n')) {
f20720
+				condlog(0, "malformed prkey file line for wwid: '%s'", ptr);
f20720
+				return 1;
f20720
+			}
f20720
+			ptr = ptr - KEYSIZE;
f20720
+			break;
f20720
+		}
f20720
+		ptr = strrchr(buf, '\n');
f20720
+		if (ptr == NULL) {
f20720
+			condlog(4, "couldn't file newline, assuming end of file");
f20720
+			break;
f20720
+		}
f20720
+		start = start + (ptr - buf) + 1;
f20720
+	}
f20720
+	if (cmd == PRKEY_READ) {
f20720
+		if (!ptr || *ptr == '#')
f20720
+			return 1;
f20720
+		memcpy(keystr, ptr, KEYSIZE - 1);
f20720
+		keystr[KEYSIZE - 1] = '\0';
f20720
+		return 0;
f20720
+	}
f20720
+	if (!ptr && !keystr)
f20720
+		return 0;
f20720
+	if (ptr) {
f20720
+		if (lseek(fd, start + (ptr - buf), SEEK_SET) < 0) {
f20720
+			condlog(0, "prkey write lseek failed : %s",
f20720
+				strerror(errno));
f20720
+			return 1;
f20720
+		}
f20720
+	}
f20720
+	if (!keystr) {
f20720
+		if (safe_write(fd, "#", 1) < 0) {
f20720
+			condlog(0, "failed to write to prkey file : %s",
f20720
+				strerror(errno));
f20720
+			return 1;
f20720
+		}
f20720
+		return 0;
f20720
+	}
f20720
+	if (!ptr) {
f20720
+		if (lseek(fd, 0, SEEK_END) < 0) {
f20720
+			condlog(0, "prkey write lseek failed : %s",
f20720
+				strerror(errno));
f20720
+			return 1;
f20720
+		}
f20720
+	}
f20720
+	bytes = sprintf(buf, "%s %s\n", keystr, wwid);
f20720
+	if (safe_write(fd, buf, bytes) < 0) {
f20720
+		condlog(0, "failed to write to prkey file: %s",
f20720
+			strerror(errno));
f20720
+		return 1;
f20720
+	}
f20720
+	return 0;
f20720
+}
f20720
+
f20720
+int get_prkey(struct multipath *mpp, uint64_t *prkey)
f20720
+{
f20720
+	int fd;
f20720
+	int unused;
f20720
+	int ret = 1;
f20720
+	char keystr[KEYSIZE];
f20720
+
f20720
+	if (!strlen(mpp->wwid))
f20720
+		goto out;
f20720
+
f20720
+	fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER);
f20720
+	if (fd < 0)
f20720
+		goto out;
f20720
+	ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ);
f20720
+	if (ret)
f20720
+		goto out_file;
f20720
+	ret = !!parse_prkey(keystr, prkey);
f20720
+out_file:
f20720
+	close(fd);
f20720
+out:
f20720
+	return ret;
f20720
+}
f20720
+
f20720
+int set_prkey(struct multipath *mpp, uint64_t prkey)
f20720
+{
f20720
+	int fd;
f20720
+	int can_write = 1;
f20720
+	int ret = 1;
f20720
+	char keystr[KEYSIZE];
f20720
+
f20720
+	if (!strlen(mpp->wwid))
f20720
+		goto out;
f20720
+
f20720
+	fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER);
f20720
+	if (fd < 0)
f20720
+		goto out;
f20720
+	if (!can_write) {
f20720
+		condlog(0, "cannot set prkey, prkeys file is read-only");
f20720
+		goto out_file;
f20720
+	}
f20720
+	if (prkey) {
f20720
+		snprintf(keystr, KEYSIZE, "0x%016" PRIx64, prkey);
f20720
+		keystr[KEYSIZE - 1] = '\0';
f20720
+		ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_WRITE);
f20720
+	}
f20720
+	else
f20720
+		ret = do_prkey(fd, mpp->wwid, NULL, PRKEY_WRITE);
f20720
+	if (ret == 0)
f20720
+		select_reservation_key(mpp);
f20720
+	if (get_be64(mpp->reservation_key) != prkey)
f20720
+		ret = 1;
f20720
+out_file:
f20720
+	close(fd);
f20720
+out:
f20720
+	return ret;
f20720
+}
526b4e
Index: multipath-tools-130222/libmultipath/prkey.h
f20720
===================================================================
f20720
--- /dev/null
526b4e
+++ multipath-tools-130222/libmultipath/prkey.h
f20720
@@ -0,0 +1,19 @@
f20720
+#ifndef _PRKEY_H
f20720
+#define _PRKEY_H
f20720
+
f20720
+#include "structs.h"
f20720
+#include <inttypes.h>
f20720
+
f20720
+#define PRKEYS_FILE_HEADER \
f20720
+"# Multipath persistent reservation keys, Version : 1.0\n" \
f20720
+"# NOTE: this file is automatically maintained by the multipathd program.\n" \
f20720
+"# You should not need to edit this file in normal circumstances.\n" \
f20720
+"#\n" \
f20720
+"# Format:\n" \
f20720
+"# prkey wwid\n" \
f20720
+"#\n"
f20720
+
f20720
+int set_prkey(struct multipath *mpp, uint64_t prkey);
f20720
+int get_prkey(struct multipath *mpp, uint64_t *prkey);
f20720
+
f20720
+#endif /* _PRKEY_H */
526b4e
Index: multipath-tools-130222/libmultipath/propsel.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/propsel.c
526b4e
+++ multipath-tools-130222/libmultipath/propsel.c
f20720
@@ -18,6 +18,7 @@
f20720
 #include "prio.h"
f20720
 #include "discovery.h"
f20720
 #include "prioritizers/alua_rtpg.h"
f20720
+#include "prkey.h"
f20720
 #include <inttypes.h>
f20720
 
f20720
 pgpolicyfn *pgpolicies[] = {
f20720
@@ -711,44 +712,39 @@ select_flush_on_last_del(struct multipat
f20720
 extern int
f20720
 select_reservation_key (struct multipath * mp)
f20720
 {
f20720
-	int j;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey = 0;
f20720
-
f20720
-	mp->reservation_key = NULL;
f20720
-
f20720
-	if (mp->mpe && mp->mpe->reservation_key) {
f20720
-		keyp =  mp->mpe->reservation_key;
f20720
-		for (j = 0; j < 8; ++j) {
f20720
-			if (j > 0)
f20720
-				prkey <<= 8;
f20720
-			prkey |= *keyp;
f20720
-			++keyp;
f20720
-		}
f20720
-
f20720
-		condlog(3, "%s: reservation_key = 0x%" PRIx64 " "
f20720
-				"(multipath setting)",  mp->alias, prkey);
f20720
+	uint64_t prkey;
f20720
+	char *origin = NULL;
f20720
+	char *from_file = "";
f20720
 
f20720
+	if (mp->mpe && mp->mpe->prkey_source != PRKEY_SOURCE_NONE) {
f20720
+		mp->prkey_source = mp->mpe->prkey_source;
f20720
 		mp->reservation_key = mp->mpe->reservation_key;
f20720
-		return 0;
f20720
+		origin = "multipath setting";
f20720
+		goto out;
f20720
 	}
f20720
 
f20720
-	if (conf->reservation_key) {
f20720
-		keyp = conf->reservation_key;
f20720
-		for (j = 0; j < 8; ++j) {
f20720
-			if (j > 0)
f20720
-				prkey <<= 8;
f20720
-			prkey |= *keyp;
f20720
-			++keyp;
f20720
-		}
f20720
-
f20720
-		condlog(3, "%s: reservation_key  = 0x%" PRIx64
f20720
-				" (config file default)", mp->alias, prkey);
f20720
-
f20720
+	if (conf->prkey_source != PRKEY_SOURCE_NONE) {
f20720
+		mp->prkey_source = conf->prkey_source;
f20720
 		mp->reservation_key = conf->reservation_key;
f20720
-		return 0;
f20720
+		origin = "config file default";
f20720
+		goto out;
f20720
 	}
f20720
 
f20720
+	put_be64(mp->reservation_key, 0);
f20720
+	mp->prkey_source = PRKEY_SOURCE_NONE;
f20720
+	return 0;
f20720
+out:
f20720
+	if (mp->prkey_source == PRKEY_SOURCE_FILE) {
f20720
+		from_file = " (from prkeys file)";
f20720
+		if (get_prkey(mp, &prkey) != 0)
f20720
+			put_be64(mp->reservation_key, 0);
f20720
+		else
f20720
+			put_be64(mp->reservation_key, prkey);
f20720
+	}
f20720
+	if (get_be64(mp->reservation_key))
f20720
+		condlog(0, "%s: reservation_key = 0x%" PRIx64 " (%s)%s",
f20720
+			mp->alias, get_be64(mp->reservation_key), origin,
f20720
+			from_file);
f20720
 	return 0;
f20720
 }
f20720
 
526b4e
Index: multipath-tools-130222/libmultipath/structs.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/structs.h
526b4e
+++ multipath-tools-130222/libmultipath/structs.h
f20720
@@ -2,8 +2,10 @@
f20720
 #define _STRUCTS_H
f20720
 
f20720
 #include <sys/types.h>
f20720
+#include <inttypes.h>
f20720
 
f20720
 #include "prio.h"
f20720
+#include "byteorder.h"
f20720
 
f20720
 #define WWID_SIZE		128
f20720
 #define SERIAL_SIZE		65
f20720
@@ -27,7 +29,6 @@
f20720
 #define NO_PATH_RETRY_FAIL	-1
f20720
 #define NO_PATH_RETRY_QUEUE	-2
f20720
 
f20720
-
f20720
 enum free_path_mode {
f20720
 	KEEP_PATHS,
f20720
 	FREE_PATHS
f20720
@@ -169,6 +170,12 @@ enum missing_udev_info_states {
f20720
 	INFO_REQUESTED,
f20720
 };
f20720
 
f20720
+enum prkey_sources {
f20720
+	PRKEY_SOURCE_NONE,
f20720
+	PRKEY_SOURCE_CONF,
f20720
+	PRKEY_SOURCE_FILE,
f20720
+};
f20720
+
f20720
 struct sg_id {
f20720
 	int host_no;
f20720
 	int channel;
f20720
@@ -298,8 +305,9 @@ struct multipath {
f20720
 	/* checkers shared data */
f20720
 	void * mpcontext;
f20720
 	
f20720
-	/* persistent management data*/
f20720
-	unsigned char * reservation_key;
f20720
+	/* persistent management data */
f20720
+	int prkey_source;
f20720
+	struct be64 reservation_key;
f20720
 	unsigned char prflag;
f20720
 };
f20720
 
526b4e
Index: multipath-tools-130222/libmultipath/util.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/util.c
526b4e
+++ multipath-tools-130222/libmultipath/util.c
f20720
@@ -5,12 +5,14 @@
f20720
 #include <unistd.h>
f20720
 #include <sys/vfs.h>
f20720
 #include <linux/magic.h>
f20720
+#include <errno.h>
f20720
 
f20720
 #include "debug.h"
f20720
 #include "memory.h"
f20720
 #include "checkers.h"
f20720
 #include "vector.h"
f20720
 #include "structs.h"
f20720
+#include "util.h"
f20720
 
f20720
 void
f20720
 strchop(char *str)
f20720
@@ -297,3 +299,35 @@ int in_initrd(void) {
f20720
 
f20720
 	return saved;
f20720
 }
f20720
+
f20720
+int parse_prkey(char *ptr, uint64_t *prkey)
f20720
+{
f20720
+	if (!ptr)
f20720
+		return 1;
f20720
+	if (*ptr == '0')
f20720
+		ptr++;
f20720
+	if (*ptr == 'x' || *ptr == 'X')
f20720
+		ptr++;
f20720
+	if (*ptr == '\0' || strlen(ptr) > 16)
f20720
+		return 1;
f20720
+	if (strlen(ptr) != strspn(ptr, "0123456789aAbBcCdDeEfF"))
f20720
+		return 1;
f20720
+	if (sscanf(ptr, "%" SCNx64 "", prkey) != 1)
f20720
+		return 1;
f20720
+	return 0;
f20720
+}
f20720
+
f20720
+int safe_write(int fd, const void *buf, size_t count)
f20720
+{
f20720
+	while (count > 0) {
f20720
+		ssize_t r = write(fd, buf, count);
f20720
+		if (r < 0) {
f20720
+			if (errno == EINTR || errno == EAGAIN)
f20720
+				continue;
f20720
+			return -errno;
f20720
+		}
f20720
+		count -= r;
f20720
+		buf = (char *)buf + r;
f20720
+	}
f20720
+	return 0;
f20720
+}
526b4e
Index: multipath-tools-130222/libmultipath/util.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/util.h
526b4e
+++ multipath-tools-130222/libmultipath/util.h
f20720
@@ -1,6 +1,8 @@
f20720
 #ifndef _UTIL_H
f20720
 #define _UTIL_H
f20720
 
f20720
+#include <inttypes.h>
f20720
+
f20720
 void strchop(char *);
f20720
 int basenamecpy (const char * src, char * dst, int);
f20720
 int filepresent (char * run);
f20720
@@ -12,6 +14,8 @@ int devt2devname (char *, int, char *);
f20720
 dev_t parse_devt(const char *dev_t);
f20720
 char *convert_dev(char *dev, int is_path_device);
f20720
 int in_initrd(void);
f20720
+int parse_prkey(char *ptr, uint64_t *prkey);
f20720
+int safe_write(int fd, const void *buf, size_t count);
f20720
 
f20720
 #define safe_sprintf(var, format, args...)	\
f20720
 	snprintf(var, sizeof(var), format, ##args) >= sizeof(var)
526b4e
Index: multipath-tools-130222/multipathd/cli.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/cli.c
526b4e
+++ multipath-tools-130222/multipathd/cli.c
f20720
@@ -190,6 +190,10 @@ load_keys (void)
f20720
 	r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0);
f20720
 	r += add_key(keys, "format", FMT, 1);
f20720
 	r += add_key(keys, "json", JSON, 0);
f20720
+	r += add_key(keys, "getprkey", GETPRKEY, 0);
f20720
+	r += add_key(keys, "setprkey", SETPRKEY, 0);
f20720
+	r += add_key(keys, "unsetprkey", UNSETPRKEY, 0);
f20720
+	r += add_key(keys, "key", KEY, 1);
f20720
 
f20720
 	if (r) {
f20720
 		free_keys(keys);
f20720
@@ -506,6 +510,9 @@ cli_init (void) {
f20720
 	add_handler(GETPRSTATUS+MAP, NULL);
f20720
 	add_handler(SETPRSTATUS+MAP, NULL);
f20720
 	add_handler(UNSETPRSTATUS+MAP, NULL);
f20720
+	add_handler(GETPRKEY+MAP, NULL);
f20720
+	add_handler(SETPRKEY+MAP+KEY, NULL);
f20720
+	add_handler(UNSETPRKEY+MAP, NULL);
f20720
 	add_handler(FORCEQ+DAEMON, NULL);
f20720
 	add_handler(RESTOREQ+DAEMON, NULL);
f20720
 
526b4e
Index: multipath-tools-130222/multipathd/cli.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/cli.h
526b4e
+++ multipath-tools-130222/multipathd/cli.h
f20720
@@ -37,6 +37,10 @@ enum {
f20720
 	__UNSETPRSTATUS,
f20720
 	__FMT,
f20720
 	__JSON,
f20720
+	__GETPRKEY,
f20720
+	__SETPRKEY,
f20720
+	__UNSETPRKEY,
f20720
+	__KEY,
f20720
 };
f20720
 
f20720
 #define LIST		(1 << __LIST)
f20720
@@ -76,6 +80,10 @@ enum {
f20720
 #define UNSETPRSTATUS	(1ULL << __UNSETPRSTATUS)
f20720
 #define FMT		(1ULL << __FMT)
f20720
 #define JSON		(1ULL << __JSON)
f20720
+#define GETPRKEY	(1ULL << __GETPRKEY)
f20720
+#define SETPRKEY	(1ULL << __SETPRKEY)
f20720
+#define UNSETPRKEY	(1ULL << __UNSETPRKEY)
f20720
+#define KEY		(1ULL << __KEY)
f20720
 
f20720
 #define INITIAL_REPLY_LEN	1200
f20720
 
526b4e
Index: multipath-tools-130222/multipathd/cli_handlers.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/cli_handlers.c
526b4e
+++ multipath-tools-130222/multipathd/cli_handlers.c
f20720
@@ -18,6 +18,7 @@
f20720
 #include <errno.h>
f20720
 #include <libudev.h>
f20720
 #include <util.h>
f20720
+#include <prkey.h>
f20720
 
f20720
 #include "main.h"
f20720
 #include "cli.h"
526b4e
@@ -1234,3 +1235,71 @@ cli_unsetprstatus(void * v, char ** repl
f20720
 
f20720
 	return 0;
f20720
 }
f20720
+
f20720
+int
f20720
+cli_getprkey(void * v, char ** reply, int * len, void * data)
f20720
+{
f20720
+	struct multipath * mpp;
f20720
+	struct vectors * vecs = (struct vectors *)data;
f20720
+	char *mapname = get_keyparam(v, MAP);
f20720
+
f20720
+	mapname = convert_dev(mapname, 0);
f20720
+	condlog(3, "%s: get persistent reservation key (operator)", mapname);
f20720
+	mpp = find_mp_by_str(vecs->mpvec, mapname);
f20720
+
f20720
+	if (!mpp)
f20720
+		return 1;
f20720
+
f20720
+	*reply = malloc(20);
f20720
+
f20720
+	if (!get_be64(mpp->reservation_key)) {
f20720
+		sprintf(*reply, "none\n");
f20720
+		*len = strlen(*reply) + 1;
f20720
+		return 0;
f20720
+	}
f20720
+	snprintf(*reply, 20, "0x%" PRIx64 "\n",
f20720
+		 get_be64(mpp->reservation_key));
f20720
+	(*reply)[19] = '\0';
f20720
+	*len = strlen(*reply) + 1;
f20720
+	return 0;
f20720
+}
f20720
+
f20720
+int
f20720
+cli_unsetprkey(void * v, char ** reply, int * len, void * data)
f20720
+{
f20720
+	struct multipath * mpp;
f20720
+	struct vectors * vecs = (struct vectors *)data;
f20720
+	char *mapname = get_keyparam(v, MAP);
f20720
+
f20720
+	mapname = convert_dev(mapname, 0);
f20720
+	condlog(3, "%s: unset persistent reservation key (operator)", mapname);
f20720
+	mpp = find_mp_by_str(vecs->mpvec, mapname);
f20720
+
f20720
+	if (!mpp)
f20720
+		return 1;
f20720
+
f20720
+	return set_prkey(mpp, 0);
f20720
+}
f20720
+
f20720
+int cli_setprkey(void * v, char ** reply, int * len, void * data)
f20720
+{
f20720
+	struct multipath * mpp;
f20720
+	struct vectors * vecs = (struct vectors *)data;
f20720
+	char *mapname = get_keyparam(v, MAP);
f20720
+	char *keyparam = get_keyparam(v, KEY);
f20720
+	uint64_t prkey;
f20720
+
f20720
+	mapname = convert_dev(mapname, 0);
f20720
+	condlog(3, "%s: set persistent reservation key (operator)", mapname);
f20720
+	mpp = find_mp_by_str(vecs->mpvec, mapname);
f20720
+
f20720
+	if (!mpp)
f20720
+		return 1;
f20720
+
f20720
+	if (parse_prkey(keyparam, &prkey) != 0) {
f20720
+		condlog(0, "%s: invalid prkey : '%s'", mapname, keyparam);
f20720
+		return 1;
f20720
+	}
f20720
+
f20720
+	return set_prkey(mpp, prkey);
f20720
+}
526b4e
Index: multipath-tools-130222/multipathd/cli_handlers.h
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/cli_handlers.h
526b4e
+++ multipath-tools-130222/multipathd/cli_handlers.h
f20720
@@ -42,4 +42,6 @@ int cli_reassign (void * v, char ** repl
f20720
 int cli_getprstatus(void * v, char ** reply, int * len, void * data);
f20720
 int cli_setprstatus(void * v, char ** reply, int * len, void * data);
f20720
 int cli_unsetprstatus(void * v, char ** reply, int * len, void * data);
f20720
-
f20720
+int cli_getprkey(void * v, char ** reply, int * len, void * data);
f20720
+int cli_setprkey(void * v, char ** reply, int * len, void * data);
f20720
+int cli_unsetprkey(void * v, char ** reply, int * len, void * data);
526b4e
Index: multipath-tools-130222/multipathd/main.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/main.c
526b4e
+++ multipath-tools-130222/multipathd/main.c
f20720
@@ -57,6 +57,7 @@
f20720
 #include <uevent.h>
f20720
 #include <log.h>
f20720
 #include <file.h>
f20720
+#include <prkey.h>
f20720
 
f20720
 #include "main.h"
f20720
 #include "pidfile.h"
f20720
@@ -1050,6 +1051,9 @@ uxlsnrloop (void * ap)
f20720
 	set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus);
f20720
 	set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus);
f20720
 	set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus);
f20720
+	set_handler_callback(GETPRKEY+MAP, cli_getprkey);
f20720
+	set_handler_callback(SETPRKEY+MAP+KEY, cli_setprkey);
f20720
+	set_handler_callback(UNSETPRKEY+MAP, cli_unsetprkey);
f20720
 	set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q);
f20720
 	set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q);
f20720
 
f20720
@@ -2266,10 +2270,8 @@ main (int argc, char *argv[])
f20720
 void *  mpath_pr_event_handler_fn (void * pathp )
f20720
 {
f20720
 	struct multipath * mpp;
f20720
-	int i,j, ret, isFound;
f20720
+	int i, ret, isFound;
f20720
 	struct path * pp = (struct path *)pathp;
f20720
-	unsigned char *keyp;
f20720
-	uint64_t prkey;
f20720
 	struct prout_param_descriptor *param;
f20720
 	struct prin_resp *resp;
f20720
 
f20720
@@ -2297,22 +2299,15 @@ void *  mpath_pr_event_handler_fn (void
f20720
 		ret = MPATH_PR_SUCCESS;
f20720
 		goto out;
f20720
 	}
f20720
-	prkey = 0;
f20720
-	keyp = (unsigned char *)mpp->reservation_key;
f20720
-	for (j = 0; j < 8; ++j) {
f20720
-		if (j > 0)
f20720
-			prkey <<= 8;
f20720
-		prkey |= *keyp;
f20720
-		++keyp;
f20720
-	}
f20720
-	condlog(2, "Multipath  reservation_key: 0x%" PRIx64 " ", prkey);
f20720
+	condlog(2, "Multipath  reservation_key: 0x%" PRIx64 " ",
f20720
+		get_be64(mpp->reservation_key));
f20720
 
f20720
 	isFound =0;
f20720
 	for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
f20720
 	{
f20720
 		condlog(2, "PR IN READKEYS[%d]  reservation key:",i);
f20720
 		dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , -1);
f20720
-		if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
f20720
+		if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
f20720
 		{
f20720
 			condlog(2, "%s: pr key found in prin readkeys response", mpp->alias);
f20720
 			isFound =1;
f20720
@@ -2329,11 +2324,7 @@ void *  mpath_pr_event_handler_fn (void
f20720
 
f20720
 	param= malloc(sizeof(struct prout_param_descriptor));
f20720
 	memset(param, 0 , sizeof(struct prout_param_descriptor));
f20720
-
f20720
-	for (j = 7; j >= 0; --j) {
f20720
-		param->sa_key[j] = (prkey & 0xff);
f20720
-		prkey >>= 8;
f20720
-	}
f20720
+	memcpy(param->sa_key, &mpp->reservation_key, 8);
f20720
 	param->num_transportid = 0;
f20720
 
f20720
 	condlog(3, "device %s:%s", pp->dev, pp->mpp->wwid);
f20720
@@ -2360,7 +2351,7 @@ int mpath_pr_event_handle(struct path *p
f20720
 
f20720
 	mpp = pp->mpp;
f20720
 
f20720
-	if (!mpp->reservation_key)
f20720
+	if (!get_be64(mpp->reservation_key))
f20720
 		return -1;
f20720
 
f20720
 	pthread_attr_init(&attr);
526b4e
Index: multipath-tools-130222/libmultipath/Makefile
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/libmultipath/Makefile
526b4e
+++ multipath-tools-130222/libmultipath/Makefile
f20720
@@ -16,7 +16,7 @@ OBJS = memory.o parser.o vector.o devmap
f20720
        pgpolicies.o debug.o regex.o defaults.o uevent.o \
f20720
        switchgroup.o uxsock.o print.o alias.o log_pthread.o \
f20720
        log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
f20720
-       lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o
f20720
+       lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o
f20720
 
f20720
 LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
f20720
 
526b4e
Index: multipath-tools-130222/multipath/multipath.conf.5
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipath/multipath.conf.5
526b4e
+++ multipath-tools-130222/multipath/multipath.conf.5
f20720
@@ -414,6 +414,13 @@ of the wwids for LUNs it has created mul
f20720
 Defaults to
f20720
 .I /etc/multipath/wwids
f20720
 .TP
f20720
+.B prkeys_file
f20720
+The full pathname of the prkeys file, which is used by multipathd to keep
f20720
+track of the reservation key used for a specific WWID, when
f20720
+\fIreservation_key\fR is set to \fIfile\fR.
f20720
+Defaults to
f20720
+.I /etc/multipath/prkeys
f20720
+.TP
f20720
 .B log_checker_err
f20720
 If set to
f20720
 .I once
f20720
@@ -428,7 +435,16 @@ This is the service action reservation k
f20720
 set for all multipath devices using persistent reservations, and it must be
f20720
 the same as the RESERVATION KEY field of the PERSISTENT RESERVE OUT parameter
f20720
 list which contains an 8-byte value provided by the application client to the
f20720
-device server to identify the I_T nexus. It is unset by default.
f20720
+device server to identify the I_T nexus.
f20720
+.RS
f20720
+.PP
f20720
+Alternatively, this can be set to \fBfile\fR, which will store the RESERVATION
f20720
+KEY registered by mpathpersist in the \fIprkeys_file\fR. multipathd will then
f20720
+use this key to register additional paths as they appear.  When the
f20720
+registration is removed, the RESERVATION KEY is removed from the
f20720
+\fIprkeys_file\fR.
f20720
+It is unset by default.
f20720
+.RE
f20720
 .TP
f20720
 .B retain_attached_hw_handler
f20720
 If set to
526b4e
Index: multipath-tools-130222/multipathd/multipathd.8
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/multipathd/multipathd.8
526b4e
+++ multipath-tools-130222/multipathd/multipathd.8
526b4e
@@ -161,6 +161,19 @@ Disable persistent reservation managemen
f20720
 .B map|multipath $map getprstatus
f20720
 Get the current persistent reservation management status of $map
f20720
 .TP
f20720
+.B map|multipath $map getprkey
f20720
+Get the current persistent reservation key associated with $map.
f20720
+.TP
f20720
+.B map|multipath $map setprkey key $key
f20720
+Set the persistent reservation key associated with $map to $key in the
f20720
+\fIprkeys_file\fR. This key will only be used by multipathd if
f20720
+\fIreservation_key\fR is set to \fIfile\fR in \fI/etc/multipath.conf\fR.
f20720
+.TP
f20720
+.B map|multipath $map unsetprkey
f20720
+Remove the persistent reservation key associated with $map from the
f20720
+\fIprkeys_file\fR. This will only unset the key used by multipathd if
f20720
+\fIreservation_key\fR is set to \fIfile\fR in \fI/etc/multipath.conf\fR.
f20720
+.TP
f20720
 .B quit|exit
f20720
 End interactive session.
f20720
 .TP
526b4e
Index: multipath-tools-130222/mpathpersist/main.c
f20720
===================================================================
526b4e
--- multipath-tools-130222.orig/mpathpersist/main.c
526b4e
+++ multipath-tools-130222/mpathpersist/main.c
f20720
@@ -5,6 +5,7 @@
f20720
 #include <fcntl.h>
f20720
 #include <checkers.h>
f20720
 #include <vector.h>
f20720
+#include <util.h>
f20720
 #include <structs.h>
f20720
 #include <getopt.h>
f20720
 #include <libudev.h>
f20720
@@ -139,7 +140,7 @@ int main (int argc, char * argv[])
f20720
 				++num_prout_param;
f20720
 				break;
f20720
 			case 'K':
f20720
-				if (1 != sscanf (optarg, "%" SCNx64 "", &param_rk))
f20720
+				if (parse_prkey(optarg, &param_rk) != 0)
f20720
 				{
f20720
 					fprintf (stderr, "bad argument to '--param-rk'\n");
f20720
 					return MPATH_PR_SYNTAX_ERROR;
f20720
@@ -148,7 +149,7 @@ int main (int argc, char * argv[])
f20720
 				break;
f20720
 
f20720
 			case 'S':
f20720
-				if (1 != sscanf (optarg, "%" SCNx64 "", &param_sark))
f20720
+				if (parse_prkey(optarg, &param_sark) != 0)
f20720
 				{
f20720
 					fprintf (stderr, "bad argument to '--param-sark'\n");
f20720
 					return MPATH_PR_SYNTAX_ERROR;