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

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