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

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