Blame SOURCES/0224-RHBZ-1452210-prkey.patch

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