[dm-devel] [PATCH 1/5] libmpathpersist: split public and internal API

mwilck at suse.com mwilck at suse.com
Thu Dec 16 12:54:58 UTC 2021


From: Martin Wilck <mwilck at suse.com>

The libmpathpersist library exports symbols that are not part
of the public API. Move the respective code into a separate
source file.

Signed-off-by: Martin Wilck <mwilck at suse.com>
---
 libmpathpersist/Makefile                |   2 +-
 libmpathpersist/libmpathpersist.version |  27 +-
 libmpathpersist/mpath_persist.c         | 776 +----------------------
 libmpathpersist/mpath_persist_int.c     | 779 ++++++++++++++++++++++++
 libmpathpersist/mpath_persist_int.h     |  17 +
 libmpathpersist/mpathpr.h               |  12 -
 mpathpersist/main.c                     |   1 +
 multipathd/main.c                       |   1 +
 8 files changed, 818 insertions(+), 797 deletions(-)
 create mode 100644 libmpathpersist/mpath_persist_int.c
 create mode 100644 libmpathpersist/mpath_persist_int.h

diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
index 1e6399d..fbc401e 100644
--- a/libmpathpersist/Makefile
+++ b/libmpathpersist/Makefile
@@ -10,7 +10,7 @@ LDFLAGS += -L$(multipathdir) -L$(mpathcmddir)
 
 LIBDEPS += -lmultipath -lmpathcmd -ldevmapper -lpthread -ldl
 
-OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
+OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o mpath_persist_int.o
 
 all: $(DEVLIB) man
 
diff --git a/libmpathpersist/libmpathpersist.version b/libmpathpersist/libmpathpersist.version
index fa312f6..a8c6aae 100644
--- a/libmpathpersist/libmpathpersist.version
+++ b/libmpathpersist/libmpathpersist.version
@@ -10,27 +10,28 @@
  *
  * See libmultipath.version for general policy about version numbers.
  */
-LIBMPATHPERSIST_2.0.0 {
+LIBMPATHPERSIST_2.1.0 {
 global:
-
-	__mpath_persistent_reserve_in;
-	__mpath_persistent_reserve_out;
-	dumpHex;
-	mpath_alloc_prin_response;
+	/* public API as defined in mpath_persist.h */
+	libmpathpersist_exit;
+	libmpathpersist_init;
 	mpath_lib_exit;
 	mpath_lib_init;
 	mpath_mx_alloc_len;
+	mpath_persistent_reserve_free_vecs;
+	__mpath_persistent_reserve_in;
 	mpath_persistent_reserve_in;
 	mpath_persistent_reserve_init_vecs;
+	__mpath_persistent_reserve_out;
 	mpath_persistent_reserve_out;
-	mpath_persistent_reserve_free_vecs;
+local: *;
+};
+
+__LIBMPATHPERSIST_INT_1.0.0 {
+	/* Internal use by multipath-tools */
+	dumpHex;
+	mpath_alloc_prin_response;
 	prin_do_scsi_ioctl;
 	prout_do_scsi_ioctl;
 	update_map_pr;
-
-	/* added in 1.1.0 */
-	libmpathpersist_init;
-	libmpathpersist_exit;
-
-local: *;
 };
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 3097c81..6cfcdde 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -1,39 +1,13 @@
 #include <libdevmapper.h>
-#include "defaults.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include "vector.h"
-#include "checkers.h"
-#include "structs.h"
-#include "structs_vec.h"
-#include <libudev.h>
 
-#include "prio.h"
-#include <unistd.h>
-#include "devmapper.h"
-#include "debug.h"
-#include "config.h"
-#include "switchgroup.h"
-#include "discovery.h"
-#include "configure.h"
-#include "dmparser.h"
-#include <ctype.h>
-#include "propsel.h"
 #include "util.h"
-#include "unaligned.h"
+#include "vector.h"
+#include "config.h"
+#include "debug.h"
+#include "devmapper.h"
 
 #include "mpath_persist.h"
-#include "mpathpr.h"
-#include "mpath_pr_ioctl.h"
-
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#define __STDC_FORMAT_MACROS 1
+#include "mpath_persist_int.h"
 
 extern struct udev *udev;
 
@@ -97,42 +71,6 @@ int libmpathpersist_exit(void)
 	return 0;
 }
 
-int
-mpath_prin_activepath (struct multipath *mpp, int rq_servact,
-	struct prin_resp * resp, int noisy)
-{
-	int i,j, ret = MPATH_PR_DMMP_ERROR;
-	struct pathgroup *pgp = NULL;
-	struct path *pp = NULL;
-
-	vector_foreach_slot (mpp->pg, pgp, j){
-		vector_foreach_slot (pgp->paths, pp, i){
-			if (!((pp->state == PATH_UP) ||
-			      (pp->state == PATH_GHOST))){
-				condlog(2, "%s: %s not available. Skip.",
-					mpp->wwid, pp->dev);
-				condlog(3, "%s: status = %d.",
-					mpp->wwid, pp->state);
-				continue;
-			}
-
-			condlog(3, "%s: sending pr in command to %s ",
-				mpp->wwid, pp->dev);
-			ret = mpath_send_prin_activepath(pp->dev, rq_servact,
-							 resp, noisy);
-			switch(ret)
-			{
-				case MPATH_PR_SUCCESS:
-				case MPATH_PR_SENSE_INVALID_OP:
-					return ret;
-				default:
-					continue;
-			}
-		}
-	}
-	return ret;
-}
-
 static vector curmp;
 static vector pathvec;
 
@@ -182,83 +120,6 @@ int mpath_persistent_reserve_init_vecs(int verbose)
 	return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
 }
 
-static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
-			 struct multipath **pmpp)
-{
-	int ret = MPATH_PR_DMMP_ERROR;
-	struct stat info;
-	int major, minor;
-	char *alias;
-	struct multipath *mpp;
-
-	if (fstat(fd, &info) != 0){
-		condlog(0, "stat error fd=%d", fd);
-		return MPATH_PR_FILE_ERROR;
-	}
-	if(!S_ISBLK(info.st_mode)){
-		condlog(3, "Failed to get major:minor. fd=%d", fd);
-		return MPATH_PR_FILE_ERROR;
-	}
-
-	major = major(info.st_rdev);
-	minor = minor(info.st_rdev);
-	condlog(4, "Device  %d:%d", major, minor);
-
-	/* get alias from major:minor*/
-	alias = dm_mapname(major, minor);
-	if (!alias){
-		condlog(0, "%d:%d failed to get device alias.", major, minor);
-		return MPATH_PR_DMMP_ERROR;
-	}
-
-	condlog(3, "alias = %s", alias);
-
-	if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
-		condlog(3, "%s: not a multipath device.", alias);
-		goto out;
-	}
-
-	/* get info of all paths from the dm device     */
-	if (get_mpvec(curmp, pathvec, alias)){
-		condlog(0, "%s: failed to get device info.", alias);
-		goto out;
-	}
-
-	mpp = find_mp_by_alias(curmp, alias);
-
-	if (!mpp) {
-		condlog(0, "%s: devmap not registered.", alias);
-		goto out;
-	}
-
-	ret = MPATH_PR_SUCCESS;
-	if (pmpp)
-		*pmpp = mpp;
-	if (palias) {
-		*palias = alias;
-		alias = NULL;
-	}
-out:
-	free(alias);
-	return ret;
-}
-
-static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
-	int fd, int rq_servact, struct prin_resp *resp, int noisy)
-{
-	struct multipath *mpp;
-	int ret;
-
-	ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
-	if (ret != MPATH_PR_SUCCESS)
-		return ret;
-
-	ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
-
-	return ret;
-}
-
-
 int __mpath_persistent_reserve_in (int fd, int rq_servact,
 	struct prin_resp *resp, int noisy)
 {
@@ -266,86 +127,6 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact,
 					      resp, noisy);
 }
 
-static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
-	int rq_servact, int rq_scope, unsigned int rq_type,
-	struct prout_param_descriptor *paramp, int noisy)
-{
-	struct multipath *mpp;
-	char *alias;
-	int ret;
-	uint64_t prkey;
-	struct config *conf;
-
-	ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
-	if (ret != MPATH_PR_SUCCESS)
-		return ret;
-
-	conf = get_multipath_config();
-	select_reservation_key(conf, mpp);
-	select_all_tg_pt(conf, mpp);
-	put_multipath_config(conf);
-
-	memcpy(&prkey, paramp->sa_key, 8);
-	if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
-	    (rq_servact == MPATH_PROUT_REG_IGN_SA ||
-	     (rq_servact == MPATH_PROUT_REG_SA &&
-	      (!get_be64(mpp->reservation_key) ||
-	       memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
-		memcpy(&mpp->reservation_key, paramp->sa_key, 8);
-		if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
-				       paramp->sa_flags)) {
-			condlog(0, "%s: failed to set prkey for multipathd.",
-				alias);
-			ret = MPATH_PR_DMMP_ERROR;
-			goto out1;
-		}
-	}
-
-	if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
-	    memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
-	    (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
-		condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
-		ret = MPATH_PR_SYNTAX_ERROR;
-		goto out1;
-	}
-
-	switch(rq_servact)
-	{
-	case MPATH_PROUT_REG_SA:
-	case MPATH_PROUT_REG_IGN_SA:
-		ret= mpath_prout_reg(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
-		break;
-	case MPATH_PROUT_RES_SA :
-	case MPATH_PROUT_PREE_SA :
-	case MPATH_PROUT_PREE_AB_SA :
-	case MPATH_PROUT_CLEAR_SA:
-		ret = mpath_prout_common(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
-		break;
-	case MPATH_PROUT_REL_SA:
-		ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
-		break;
-	default:
-		ret = MPATH_PR_OTHER;
-		goto out1;
-	}
-
-	if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
-				(rq_servact ==  MPATH_PROUT_REG_IGN_SA)))
-	{
-		if (prkey == 0) {
-			update_prflag(alias, 0);
-			update_prkey(alias, 0);
-		} else
-			update_prflag(alias, 1);
-	} else if ((ret == MPATH_PR_SUCCESS) && (rq_servact == MPATH_PROUT_CLEAR_SA)) {
-		update_prflag(alias, 0);
-		update_prkey(alias, 0);
-	}
-out1:
-	free(alias);
-	return ret;
-}
-
 
 int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
 	unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
@@ -384,550 +165,3 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
 	__mpath_persistent_reserve_free_vecs(curmp, pathvec);
 	return ret;
 }
-
-int
-get_mpvec (vector curmp, vector pathvec, char * refwwid)
-{
-	int i;
-	struct multipath *mpp;
-
-	vector_foreach_slot (curmp, mpp, i){
-		/*
-		 * discard out of scope maps
-		 */
-		if (!mpp->alias) {
-			condlog(0, "%s: map with empty alias!", __func__);
-			continue;
-		}
-
-		if (mpp->pg != NULL)
-			/* Already seen this one */
-			continue;
-
-		if (refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE - 1))
-			continue;
-
-		if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK ||
-		    update_mpp_paths(mpp, pathvec)) {
-			condlog(1, "error parsing map %s", mpp->wwid);
-			remove_map(mpp, pathvec, curmp);
-			i--;
-		} else
-			extract_hwe_from_path(mpp);
-	}
-	return MPATH_PR_SUCCESS ;
-}
-
-int mpath_send_prin_activepath (char * dev, int rq_servact,
-				struct prin_resp * resp, int noisy)
-{
-
-	int rc;
-
-	rc = prin_do_scsi_ioctl(dev, rq_servact, resp,  noisy);
-
-	return (rc);
-}
-
-int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
-{
-
-	int i, j, k;
-	struct pathgroup *pgp = NULL;
-	struct path *pp = NULL;
-	int rollback = 0;
-	int active_pathcount=0;
-	int rc;
-	int count=0;
-	int status = MPATH_PR_SUCCESS;
-	int all_tg_pt;
-	uint64_t sa_key = 0;
-
-	if (!mpp)
-		return MPATH_PR_DMMP_ERROR;
-
-	all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON ||
-		     paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK);
-	active_pathcount = count_active_paths(mpp);
-
-	if (active_pathcount == 0) {
-		condlog (0, "%s: no path available", mpp->wwid);
-		return MPATH_PR_DMMP_ERROR;
-	}
-
-	struct threadinfo thread[active_pathcount];
-	int hosts[active_pathcount];
-
-	memset(thread, 0, sizeof(thread));
-
-	/* init thread parameter */
-	for (i =0; i< active_pathcount; i++){
-		hosts[i] = -1;
-		thread[i].param.rq_servact = rq_servact;
-		thread[i].param.rq_scope = rq_scope;
-		thread[i].param.rq_type = rq_type;
-		thread[i].param.paramp = paramp;
-		thread[i].param.noisy = noisy;
-		thread[i].param.status = MPATH_PR_SKIP;
-
-		condlog (3, "THREAD ID [%d] INFO]", i);
-		condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
-		condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
-		condlog (3, "rq_type=%d ", thread[i].param.rq_type);
-		condlog (3, "rkey=");
-		condlog (3, "paramp->sa_flags =%02x ",
-			 thread[i].param.paramp->sa_flags);
-		condlog (3, "noisy=%d ", thread[i].param.noisy);
-		condlog (3, "status=%d ", thread[i].param.status);
-	}
-
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-	vector_foreach_slot (mpp->pg, pgp, j){
-		vector_foreach_slot (pgp->paths, pp, i){
-			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
-				condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
-				continue;
-			}
-			if (all_tg_pt && pp->sg_id.host_no != -1) {
-				for (k = 0; k < count; k++) {
-					if (pp->sg_id.host_no == hosts[k]) {
-						condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no);
-						break;
-					}
-				}
-				if (k < count)
-					continue;
-			}
-			strlcpy(thread[count].param.dev, pp->dev,
-				FILE_NAME_SIZE);
-
-			if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
-				/*
-				 * Clearing SPEC_I_PT as transportids are already registered by now.
-				 */
-				thread[count].param.paramp->sa_flags &= (~MPATH_F_SPEC_I_PT_MASK);
-			}
-
-			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
-
-			rc = pthread_create(&thread[count].id, &attr, mpath_prout_pthread_fn, (void *)(&thread[count].param));
-			if (rc){
-				condlog (0, "%s: failed to create thread %d", mpp->wwid, rc);
-				thread[count].param.status = MPATH_PR_THREAD_ERROR;
-			}
-			else
-				hosts[count] = pp->sg_id.host_no;
-			count = count + 1;
-		}
-	}
-	for( i=0; i < count ; i++){
-		if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
-			rc = pthread_join(thread[i].id, NULL);
-			if (rc){
-				condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
-			}
-		}
-		if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){
-			rollback = 1;
-			sa_key = get_unaligned_be64(&paramp->sa_key[0]);
-			status = MPATH_PR_RESERV_CONFLICT ;
-		}
-		if (!rollback && (status == MPATH_PR_SUCCESS)){
-			status = thread[i].param.status;
-		}
-	}
-	if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
-		condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
-		memcpy(&paramp->key, &paramp->sa_key, 8);
-		memset(&paramp->sa_key, 0, 8);
-		for( i=0 ; i < count ; i++){
-			if(thread[i].param.status == MPATH_PR_SUCCESS) {
-				rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
-						(void *)(&thread[i].param));
-				if (rc){
-					condlog (0, "%s: failed to create thread for rollback. %d",  mpp->wwid, rc);
-					thread[i].param.status = MPATH_PR_THREAD_ERROR;
-				}
-			} else
-				thread[i].param.status = MPATH_PR_SKIP;
-		}
-		for(i=0; i < count ; i++){
-			if (thread[i].param.status != MPATH_PR_SKIP &&
-			    thread[i].param.status != MPATH_PR_THREAD_ERROR) {
-				rc = pthread_join(thread[i].id, NULL);
-				if (rc){
-					condlog (3, "%s: failed to join thread while rolling back %d",
-						 mpp->wwid, i);
-				}
-			}
-		}
-	}
-
-	pthread_attr_destroy(&attr);
-	return (status);
-}
-
-void * mpath_prout_pthread_fn(void *p)
-{
-	int ret;
-	struct prout_param * param = (struct prout_param *)p;
-
-	ret = prout_do_scsi_ioctl( param->dev,param->rq_servact, param->rq_scope,
-			param->rq_type, param->paramp, param->noisy);
-	param->status = ret;
-	pthread_exit(NULL);
-}
-
-int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor* paramp, int noisy)
-{
-	int i,j, ret;
-	struct pathgroup *pgp = NULL;
-	struct path *pp = NULL;
-
-	vector_foreach_slot (mpp->pg, pgp, j){
-		vector_foreach_slot (pgp->paths, pp, i){
-			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
-				condlog (1, "%s: %s path not up. Skip",
-					 mpp->wwid, pp->dev);
-				continue;
-			}
-
-			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
-			ret = send_prout_activepath(pp->dev, rq_servact,
-						    rq_scope, rq_type,
-						    paramp, noisy);
-			return ret ;
-		}
-	}
-	condlog (0, "%s: no path available", mpp->wwid);
-	return MPATH_PR_DMMP_ERROR;
-}
-
-int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
-{
-	struct prout_param param;
-	param.rq_servact = rq_servact;
-	param.rq_scope  = rq_scope;
-	param.rq_type   = rq_type;
-	param.paramp    = paramp;
-	param.noisy = noisy;
-	param.status = -1;
-
-	pthread_t thread;
-	pthread_attr_t attr;
-	int rc;
-
-	memset(&thread, 0, sizeof(thread));
-	strlcpy(param.dev, dev, FILE_NAME_SIZE);
-	/* Initialize and set thread joinable attribute */
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-	rc = pthread_create(&thread, &attr, mpath_prout_pthread_fn, (void *)(&param));
-	if (rc){
-		condlog (3, "%s: failed to create thread %d", dev, rc);
-		return MPATH_PR_THREAD_ERROR;
-	}
-	/* Free attribute and wait for the other threads */
-	pthread_attr_destroy(&attr);
-	rc = pthread_join(thread, NULL);
-
-	return (param.status);
-}
-
-int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
-{
-	int i, j;
-	int num = 0;
-	struct pathgroup *pgp = NULL;
-	struct path *pp = NULL;
-	int active_pathcount = 0;
-	pthread_attr_t attr;
-	int rc, found = 0;
-	int count = 0;
-	int status = MPATH_PR_SUCCESS;
-	struct prin_resp resp;
-	struct prout_param_descriptor *pamp;
-	struct prin_resp *pr_buff;
-	int length;
-	struct transportid *pptr;
-
-	if (!mpp)
-		return MPATH_PR_DMMP_ERROR;
-
-	active_pathcount = count_active_paths(mpp);
-
-	if (active_pathcount == 0) {
-		condlog (0, "%s: no path available", mpp->wwid);
-		return MPATH_PR_DMMP_ERROR;
-	}
-
-	struct threadinfo thread[active_pathcount];
-	memset(thread, 0, sizeof(thread));
-	for (i = 0; i < active_pathcount; i++){
-		thread[i].param.rq_servact = rq_servact;
-		thread[i].param.rq_scope = rq_scope;
-		thread[i].param.rq_type = rq_type;
-		thread[i].param.paramp = paramp;
-		thread[i].param.noisy = noisy;
-		thread[i].param.status = MPATH_PR_SKIP;
-
-		condlog (3, " path count = %d", i);
-		condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
-		condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
-		condlog (3, "rq_type=%d ", thread[i].param.rq_type);
-		condlog (3, "noisy=%d ", thread[i].param.noisy);
-		condlog (3, "status=%d ", thread[i].param.status);
-	}
-
-	pthread_attr_init (&attr);
-	pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
-
-	vector_foreach_slot (mpp->pg, pgp, j){
-		vector_foreach_slot (pgp->paths, pp, i){
-			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
-				condlog (1, "%s: %s path not up.", mpp->wwid, pp->dev);
-				continue;
-			}
-
-			strlcpy(thread[count].param.dev, pp->dev,
-				FILE_NAME_SIZE);
-			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
-			rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
-					(void *) (&thread[count].param));
-			if (rc) {
-				condlog (0, "%s: failed to create thread. %d",  mpp->wwid, rc);
-				thread[count].param.status = MPATH_PR_THREAD_ERROR;
-			}
-			count = count + 1;
-		}
-	}
-	pthread_attr_destroy (&attr);
-	for (i = 0; i < count; i++){
-		if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
-			rc = pthread_join (thread[i].id, NULL);
-			if (rc){
-				condlog (1, "%s: failed to join thread.  %d",  mpp->wwid,  rc);
-			}
-		}
-	}
-
-	for (i = 0; i < count; i++){
-		/*  check thread status here and return the status */
-
-		if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
-			status = MPATH_PR_RESERV_CONFLICT;
-		else if (status == MPATH_PR_SUCCESS
-				&& thread[i].param.status != MPATH_PR_RESERV_CONFLICT)
-			status = thread[i].param.status;
-	}
-
-	status = mpath_prin_activepath (mpp, MPATH_PRIN_RRES_SA, &resp, noisy);
-	if (status != MPATH_PR_SUCCESS){
-		condlog (0, "%s: pr in read reservation command failed.", mpp->wwid);
-		return MPATH_PR_OTHER;
-	}
-
-	num = resp.prin_descriptor.prin_readresv.additional_length / 8;
-	if (num == 0){
-		condlog (2, "%s: Path holding reservation is released.", mpp->wwid);
-		return MPATH_PR_SUCCESS;
-	}
-	condlog (2, "%s: Path holding reservation is not avialable.", mpp->wwid);
-
-	pr_buff =  mpath_alloc_prin_response(MPATH_PRIN_RFSTAT_SA);
-	if (!pr_buff){
-		condlog (0, "%s: failed to  alloc pr in response buffer.", mpp->wwid);
-		return MPATH_PR_OTHER;
-	}
-
-	status = mpath_prin_activepath (mpp, MPATH_PRIN_RFSTAT_SA, pr_buff, noisy);
-
-	if (status != MPATH_PR_SUCCESS){
-		condlog (0,  "%s: pr in read full status command failed.",  mpp->wwid);
-		goto out;
-	}
-
-	num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
-	if (0 == num){
-		goto out;
-	}
-	length = sizeof (struct prout_param_descriptor) + (sizeof (struct transportid *));
-
-	pamp = (struct prout_param_descriptor *)malloc (length);
-	if (!pamp){
-		condlog (0, "%s: failed to alloc pr out parameter.", mpp->wwid);
-		goto out1;
-	}
-
-	memset(pamp, 0, length);
-
-	pamp->trnptid_list[0] = (struct transportid *) malloc (sizeof (struct transportid));
-	if (!pamp->trnptid_list[0]){
-		condlog (0, "%s: failed to alloc pr out transportid.", mpp->wwid);
-		goto out1;
-	}
-
-	if (get_be64(mpp->reservation_key)){
-		memcpy (pamp->key, &mpp->reservation_key, 8);
-		condlog (3, "%s: reservation key set.", mpp->wwid);
-	}
-
-	status = mpath_prout_common (mpp, MPATH_PROUT_CLEAR_SA,
-				     rq_scope, rq_type, pamp, noisy);
-
-	if (status) {
-		condlog(0, "%s: failed to send CLEAR_SA", mpp->wwid);
-		goto out1;
-	}
-
-	pamp->num_transportid = 1;
-	pptr=pamp->trnptid_list[0];
-
-	for (i = 0; i < num; i++){
-		if (get_be64(mpp->reservation_key) &&
-			memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
-			       &mpp->reservation_key, 8)){
-			/*register with tarnsport id*/
-			memset(pamp, 0, length);
-			pamp->trnptid_list[0] = pptr;
-			memset (pamp->trnptid_list[0], 0, sizeof (struct transportid));
-			memcpy (pamp->sa_key,
-					pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
-			pamp->sa_flags = MPATH_F_SPEC_I_PT_MASK;
-			pamp->num_transportid = 1;
-
-			memcpy (pamp->trnptid_list[0],
-					&pr_buff->prin_descriptor.prin_readfd.descriptors[i]->trnptid,
-					sizeof (struct transportid));
-			status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
-					pamp, noisy);
-
-			pamp->sa_flags = 0;
-			memcpy (pamp->key, pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
-			memset (pamp->sa_key, 0, 8);
-			pamp->num_transportid = 0;
-			status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
-					pamp, noisy);
-		}
-		else
-		{
-			if (get_be64(mpp->reservation_key))
-				found = 1;
-		}
-
-
-	}
-
-	if (found){
-		memset (pamp, 0, length);
-		memcpy (pamp->sa_key, &mpp->reservation_key, 8);
-		memset (pamp->key, 0, 8);
-		status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);
-	}
-
-
-	free(pptr);
-out1:
-	free (pamp);
-out:
-	free (pr_buff);
-	return (status);
-}
-
-void * mpath_alloc_prin_response(int prin_sa)
-{
-	void * ptr = NULL;
-	int size=0;
-	switch (prin_sa)
-	{
-		case MPATH_PRIN_RKEY_SA:
-			size = sizeof(struct prin_readdescr);
-			break;
-		case MPATH_PRIN_RRES_SA:
-			size = sizeof(struct prin_resvdescr);
-			break;
-		case MPATH_PRIN_RCAP_SA:
-			size=sizeof(struct prin_capdescr);
-			break;
-		case MPATH_PRIN_RFSTAT_SA:
-			size = sizeof(struct print_fulldescr_list) +
-				sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
-			break;
-	}
-	if (size > 0)
-	{
-		ptr = calloc(size, 1);
-	}
-	return ptr;
-}
-
-int update_map_pr(struct multipath *mpp)
-{
-	int noisy=0;
-	struct prin_resp *resp;
-	unsigned int i;
-	int ret, isFound;
-
-	if (!get_be64(mpp->reservation_key))
-	{
-		/* Nothing to do. Assuming pr mgmt feature is disabled*/
-		condlog(4, "%s: reservation_key not set in multipath.conf",
-			mpp->alias);
-		return MPATH_PR_SUCCESS;
-	}
-
-	resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
-	if (!resp)
-	{
-		condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
-		return MPATH_PR_OTHER;
-	}
-	ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
-
-	if (ret != MPATH_PR_SUCCESS )
-	{
-		condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
-		free(resp);
-		return  ret;
-	}
-
-	if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
-	{
-		condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
-		free(resp);
-		return MPATH_PR_SUCCESS;
-	}
-
-	condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias,
-		get_be64(mpp->reservation_key));
-
-	isFound =0;
-	for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
-	{
-		condlog(2, "%s: PR IN READKEYS[%d]  reservation key:", mpp->alias, i);
-		dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
-
-		if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
-		{
-			condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
-			isFound =1;
-		}
-	}
-
-	if (isFound)
-	{
-		mpp->prflag = 1;
-		condlog(2, "%s: prflag flag set.", mpp->alias );
-	}
-
-	free(resp);
-	return MPATH_PR_SUCCESS;
-}
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
new file mode 100644
index 0000000..7f6ac04
--- /dev/null
+++ b/libmpathpersist/mpath_persist_int.c
@@ -0,0 +1,779 @@
+#include <libdevmapper.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <libudev.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "vector.h"
+#include "defaults.h"
+#include "checkers.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "prio.h"
+#include "devmapper.h"
+#include "debug.h"
+#include "config.h"
+#include "switchgroup.h"
+#include "discovery.h"
+#include "configure.h"
+#include "dmparser.h"
+#include "propsel.h"
+#include "util.h"
+#include "unaligned.h"
+
+#include "mpath_persist.h"
+#include "mpath_persist_int.h"
+#include "mpathpr.h"
+#include "mpath_pr_ioctl.h"
+
+
+#define __STDC_FORMAT_MACROS 1
+
+static int mpath_send_prin_activepath (char * dev, int rq_servact,
+				struct prin_resp * resp, int noisy)
+{
+
+	int rc;
+
+	rc = prin_do_scsi_ioctl(dev, rq_servact, resp,  noisy);
+
+	return (rc);
+}
+
+static int mpath_prin_activepath (struct multipath *mpp, int rq_servact,
+	struct prin_resp * resp, int noisy)
+{
+	int i,j, ret = MPATH_PR_DMMP_ERROR;
+	struct pathgroup *pgp = NULL;
+	struct path *pp = NULL;
+
+	vector_foreach_slot (mpp->pg, pgp, j){
+		vector_foreach_slot (pgp->paths, pp, i){
+			if (!((pp->state == PATH_UP) ||
+			      (pp->state == PATH_GHOST))){
+				condlog(2, "%s: %s not available. Skip.",
+					mpp->wwid, pp->dev);
+				condlog(3, "%s: status = %d.",
+					mpp->wwid, pp->state);
+				continue;
+			}
+
+			condlog(3, "%s: sending pr in command to %s ",
+				mpp->wwid, pp->dev);
+			ret = mpath_send_prin_activepath(pp->dev, rq_servact,
+							 resp, noisy);
+			switch(ret)
+			{
+				case MPATH_PR_SUCCESS:
+				case MPATH_PR_SENSE_INVALID_OP:
+					return ret;
+				default:
+					continue;
+			}
+		}
+	}
+	return ret;
+}
+
+void *mpath_alloc_prin_response(int prin_sa)
+{
+	void * ptr = NULL;
+	int size=0;
+	switch (prin_sa)
+	{
+		case MPATH_PRIN_RKEY_SA:
+			size = sizeof(struct prin_readdescr);
+			break;
+		case MPATH_PRIN_RRES_SA:
+			size = sizeof(struct prin_resvdescr);
+			break;
+		case MPATH_PRIN_RCAP_SA:
+			size=sizeof(struct prin_capdescr);
+			break;
+		case MPATH_PRIN_RFSTAT_SA:
+			size = sizeof(struct print_fulldescr_list) +
+				sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
+			break;
+	}
+	if (size > 0)
+	{
+		ptr = calloc(size, 1);
+	}
+	return ptr;
+}
+
+static int get_mpvec(vector curmp, vector pathvec, char *refwwid)
+{
+	int i;
+	struct multipath *mpp;
+
+	vector_foreach_slot (curmp, mpp, i){
+		/*
+		 * discard out of scope maps
+		 */
+		if (!mpp->alias) {
+			condlog(0, "%s: map with empty alias!", __func__);
+			continue;
+		}
+
+		if (mpp->pg != NULL)
+			/* Already seen this one */
+			continue;
+
+		if (refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE - 1))
+			continue;
+
+		if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK ||
+		    update_mpp_paths(mpp, pathvec)) {
+			condlog(1, "error parsing map %s", mpp->wwid);
+			remove_map(mpp, pathvec, curmp);
+			i--;
+		} else
+			extract_hwe_from_path(mpp);
+	}
+	return MPATH_PR_SUCCESS ;
+}
+
+static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
+			 struct multipath **pmpp)
+{
+	int ret = MPATH_PR_DMMP_ERROR;
+	struct stat info;
+	int major, minor;
+	char *alias;
+	struct multipath *mpp;
+
+	if (fstat(fd, &info) != 0){
+		condlog(0, "stat error fd=%d", fd);
+		return MPATH_PR_FILE_ERROR;
+	}
+	if(!S_ISBLK(info.st_mode)){
+		condlog(3, "Failed to get major:minor. fd=%d", fd);
+		return MPATH_PR_FILE_ERROR;
+	}
+
+	major = major(info.st_rdev);
+	minor = minor(info.st_rdev);
+	condlog(4, "Device  %d:%d", major, minor);
+
+	/* get alias from major:minor*/
+	alias = dm_mapname(major, minor);
+	if (!alias){
+		condlog(0, "%d:%d failed to get device alias.", major, minor);
+		return MPATH_PR_DMMP_ERROR;
+	}
+
+	condlog(3, "alias = %s", alias);
+
+	if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
+		condlog(3, "%s: not a multipath device.", alias);
+		goto out;
+	}
+
+	/* get info of all paths from the dm device     */
+	if (get_mpvec(curmp, pathvec, alias)){
+		condlog(0, "%s: failed to get device info.", alias);
+		goto out;
+	}
+
+	mpp = find_mp_by_alias(curmp, alias);
+
+	if (!mpp) {
+		condlog(0, "%s: devmap not registered.", alias);
+		goto out;
+	}
+
+	ret = MPATH_PR_SUCCESS;
+	if (pmpp)
+		*pmpp = mpp;
+	if (palias) {
+		*palias = alias;
+		alias = NULL;
+	}
+out:
+	free(alias);
+	return ret;
+}
+
+int do_mpath_persistent_reserve_in(vector curmp, vector pathvec,
+				   int fd, int rq_servact,
+				   struct prin_resp *resp, int noisy)
+{
+	struct multipath *mpp;
+	int ret;
+
+	ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
+	if (ret != MPATH_PR_SUCCESS)
+		return ret;
+
+	ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
+
+	return ret;
+}
+
+static void *mpath_prout_pthread_fn(void *p)
+{
+	int ret;
+	struct prout_param * param = (struct prout_param *)p;
+
+	ret = prout_do_scsi_ioctl( param->dev,param->rq_servact, param->rq_scope,
+			param->rq_type, param->paramp, param->noisy);
+	param->status = ret;
+	pthread_exit(NULL);
+}
+
+static int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
+			   unsigned int rq_type,
+			   struct prout_param_descriptor * paramp, int noisy)
+{
+
+	int i, j, k;
+	struct pathgroup *pgp = NULL;
+	struct path *pp = NULL;
+	int rollback = 0;
+	int active_pathcount=0;
+	int rc;
+	int count=0;
+	int status = MPATH_PR_SUCCESS;
+	int all_tg_pt;
+	uint64_t sa_key = 0;
+
+	if (!mpp)
+		return MPATH_PR_DMMP_ERROR;
+
+	all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON ||
+		     paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK);
+	active_pathcount = count_active_paths(mpp);
+
+	if (active_pathcount == 0) {
+		condlog (0, "%s: no path available", mpp->wwid);
+		return MPATH_PR_DMMP_ERROR;
+	}
+
+	struct threadinfo thread[active_pathcount];
+	int hosts[active_pathcount];
+
+	memset(thread, 0, sizeof(thread));
+
+	/* init thread parameter */
+	for (i =0; i< active_pathcount; i++){
+		hosts[i] = -1;
+		thread[i].param.rq_servact = rq_servact;
+		thread[i].param.rq_scope = rq_scope;
+		thread[i].param.rq_type = rq_type;
+		thread[i].param.paramp = paramp;
+		thread[i].param.noisy = noisy;
+		thread[i].param.status = MPATH_PR_SKIP;
+
+		condlog (3, "THREAD ID [%d] INFO]", i);
+		condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
+		condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
+		condlog (3, "rq_type=%d ", thread[i].param.rq_type);
+		condlog (3, "rkey=");
+		condlog (3, "paramp->sa_flags =%02x ",
+			 thread[i].param.paramp->sa_flags);
+		condlog (3, "noisy=%d ", thread[i].param.noisy);
+		condlog (3, "status=%d ", thread[i].param.status);
+	}
+
+	pthread_attr_t attr;
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+	vector_foreach_slot (mpp->pg, pgp, j){
+		vector_foreach_slot (pgp->paths, pp, i){
+			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
+				condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
+				continue;
+			}
+			if (all_tg_pt && pp->sg_id.host_no != -1) {
+				for (k = 0; k < count; k++) {
+					if (pp->sg_id.host_no == hosts[k]) {
+						condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no);
+						break;
+					}
+				}
+				if (k < count)
+					continue;
+			}
+			strlcpy(thread[count].param.dev, pp->dev,
+				FILE_NAME_SIZE);
+
+			if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
+				/*
+				 * Clearing SPEC_I_PT as transportids are already registered by now.
+				 */
+				thread[count].param.paramp->sa_flags &= (~MPATH_F_SPEC_I_PT_MASK);
+			}
+
+			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
+
+			rc = pthread_create(&thread[count].id, &attr, mpath_prout_pthread_fn, (void *)(&thread[count].param));
+			if (rc){
+				condlog (0, "%s: failed to create thread %d", mpp->wwid, rc);
+				thread[count].param.status = MPATH_PR_THREAD_ERROR;
+			}
+			else
+				hosts[count] = pp->sg_id.host_no;
+			count = count + 1;
+		}
+	}
+	for( i=0; i < count ; i++){
+		if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
+			rc = pthread_join(thread[i].id, NULL);
+			if (rc){
+				condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
+			}
+		}
+		if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){
+			rollback = 1;
+			sa_key = get_unaligned_be64(&paramp->sa_key[0]);
+			status = MPATH_PR_RESERV_CONFLICT ;
+		}
+		if (!rollback && (status == MPATH_PR_SUCCESS)){
+			status = thread[i].param.status;
+		}
+	}
+	if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
+		condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
+		memcpy(&paramp->key, &paramp->sa_key, 8);
+		memset(&paramp->sa_key, 0, 8);
+		for( i=0 ; i < count ; i++){
+			if(thread[i].param.status == MPATH_PR_SUCCESS) {
+				rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
+						(void *)(&thread[i].param));
+				if (rc){
+					condlog (0, "%s: failed to create thread for rollback. %d",  mpp->wwid, rc);
+					thread[i].param.status = MPATH_PR_THREAD_ERROR;
+				}
+			} else
+				thread[i].param.status = MPATH_PR_SKIP;
+		}
+		for(i=0; i < count ; i++){
+			if (thread[i].param.status != MPATH_PR_SKIP &&
+			    thread[i].param.status != MPATH_PR_THREAD_ERROR) {
+				rc = pthread_join(thread[i].id, NULL);
+				if (rc){
+					condlog (3, "%s: failed to join thread while rolling back %d",
+						 mpp->wwid, i);
+				}
+			}
+		}
+	}
+
+	pthread_attr_destroy(&attr);
+	return (status);
+}
+
+static int send_prout_activepath(char *dev, int rq_servact, int rq_scope,
+				 unsigned int rq_type,
+				 struct prout_param_descriptor * paramp, int noisy)
+{
+	struct prout_param param;
+	param.rq_servact = rq_servact;
+	param.rq_scope  = rq_scope;
+	param.rq_type   = rq_type;
+	param.paramp    = paramp;
+	param.noisy = noisy;
+	param.status = -1;
+
+	pthread_t thread;
+	pthread_attr_t attr;
+	int rc;
+
+	memset(&thread, 0, sizeof(thread));
+	strlcpy(param.dev, dev, FILE_NAME_SIZE);
+	/* Initialize and set thread joinable attribute */
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+	rc = pthread_create(&thread, &attr, mpath_prout_pthread_fn, (void *)(&param));
+	if (rc){
+		condlog (3, "%s: failed to create thread %d", dev, rc);
+		return MPATH_PR_THREAD_ERROR;
+	}
+	/* Free attribute and wait for the other threads */
+	pthread_attr_destroy(&attr);
+	rc = pthread_join(thread, NULL);
+
+	return (param.status);
+}
+
+static int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
+			      unsigned int rq_type,
+			      struct prout_param_descriptor* paramp, int noisy)
+{
+	int i,j, ret;
+	struct pathgroup *pgp = NULL;
+	struct path *pp = NULL;
+
+	vector_foreach_slot (mpp->pg, pgp, j){
+		vector_foreach_slot (pgp->paths, pp, i){
+			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
+				condlog (1, "%s: %s path not up. Skip",
+					 mpp->wwid, pp->dev);
+				continue;
+			}
+
+			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
+			ret = send_prout_activepath(pp->dev, rq_servact,
+						    rq_scope, rq_type,
+						    paramp, noisy);
+			return ret ;
+		}
+	}
+	condlog (0, "%s: no path available", mpp->wwid);
+	return MPATH_PR_DMMP_ERROR;
+}
+
+static int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
+			   unsigned int rq_type,
+			   struct prout_param_descriptor * paramp, int noisy)
+{
+	int i, j;
+	int num = 0;
+	struct pathgroup *pgp = NULL;
+	struct path *pp = NULL;
+	int active_pathcount = 0;
+	pthread_attr_t attr;
+	int rc, found = 0;
+	int count = 0;
+	int status = MPATH_PR_SUCCESS;
+	struct prin_resp resp;
+	struct prout_param_descriptor *pamp;
+	struct prin_resp *pr_buff;
+	int length;
+	struct transportid *pptr;
+
+	if (!mpp)
+		return MPATH_PR_DMMP_ERROR;
+
+	active_pathcount = count_active_paths(mpp);
+
+	if (active_pathcount == 0) {
+		condlog (0, "%s: no path available", mpp->wwid);
+		return MPATH_PR_DMMP_ERROR;
+	}
+
+	struct threadinfo thread[active_pathcount];
+	memset(thread, 0, sizeof(thread));
+	for (i = 0; i < active_pathcount; i++){
+		thread[i].param.rq_servact = rq_servact;
+		thread[i].param.rq_scope = rq_scope;
+		thread[i].param.rq_type = rq_type;
+		thread[i].param.paramp = paramp;
+		thread[i].param.noisy = noisy;
+		thread[i].param.status = MPATH_PR_SKIP;
+
+		condlog (3, " path count = %d", i);
+		condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
+		condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
+		condlog (3, "rq_type=%d ", thread[i].param.rq_type);
+		condlog (3, "noisy=%d ", thread[i].param.noisy);
+		condlog (3, "status=%d ", thread[i].param.status);
+	}
+
+	pthread_attr_init (&attr);
+	pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
+
+	vector_foreach_slot (mpp->pg, pgp, j){
+		vector_foreach_slot (pgp->paths, pp, i){
+			if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
+				condlog (1, "%s: %s path not up.", mpp->wwid, pp->dev);
+				continue;
+			}
+
+			strlcpy(thread[count].param.dev, pp->dev,
+				FILE_NAME_SIZE);
+			condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
+			rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
+					(void *) (&thread[count].param));
+			if (rc) {
+				condlog (0, "%s: failed to create thread. %d",  mpp->wwid, rc);
+				thread[count].param.status = MPATH_PR_THREAD_ERROR;
+			}
+			count = count + 1;
+		}
+	}
+	pthread_attr_destroy (&attr);
+	for (i = 0; i < count; i++){
+		if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
+			rc = pthread_join (thread[i].id, NULL);
+			if (rc){
+				condlog (1, "%s: failed to join thread.  %d",  mpp->wwid,  rc);
+			}
+		}
+	}
+
+	for (i = 0; i < count; i++){
+		/*  check thread status here and return the status */
+
+		if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
+			status = MPATH_PR_RESERV_CONFLICT;
+		else if (status == MPATH_PR_SUCCESS
+				&& thread[i].param.status != MPATH_PR_RESERV_CONFLICT)
+			status = thread[i].param.status;
+	}
+
+	status = mpath_prin_activepath (mpp, MPATH_PRIN_RRES_SA, &resp, noisy);
+	if (status != MPATH_PR_SUCCESS){
+		condlog (0, "%s: pr in read reservation command failed.", mpp->wwid);
+		return MPATH_PR_OTHER;
+	}
+
+	num = resp.prin_descriptor.prin_readresv.additional_length / 8;
+	if (num == 0){
+		condlog (2, "%s: Path holding reservation is released.", mpp->wwid);
+		return MPATH_PR_SUCCESS;
+	}
+	condlog (2, "%s: Path holding reservation is not avialable.", mpp->wwid);
+
+	pr_buff =  mpath_alloc_prin_response(MPATH_PRIN_RFSTAT_SA);
+	if (!pr_buff){
+		condlog (0, "%s: failed to  alloc pr in response buffer.", mpp->wwid);
+		return MPATH_PR_OTHER;
+	}
+
+	status = mpath_prin_activepath (mpp, MPATH_PRIN_RFSTAT_SA, pr_buff, noisy);
+
+	if (status != MPATH_PR_SUCCESS){
+		condlog (0,  "%s: pr in read full status command failed.",  mpp->wwid);
+		goto out;
+	}
+
+	num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
+	if (0 == num){
+		goto out;
+	}
+	length = sizeof (struct prout_param_descriptor) + (sizeof (struct transportid *));
+
+	pamp = (struct prout_param_descriptor *)malloc (length);
+	if (!pamp){
+		condlog (0, "%s: failed to alloc pr out parameter.", mpp->wwid);
+		goto out1;
+	}
+
+	memset(pamp, 0, length);
+
+	pamp->trnptid_list[0] = (struct transportid *) malloc (sizeof (struct transportid));
+	if (!pamp->trnptid_list[0]){
+		condlog (0, "%s: failed to alloc pr out transportid.", mpp->wwid);
+		goto out1;
+	}
+
+	if (get_be64(mpp->reservation_key)){
+		memcpy (pamp->key, &mpp->reservation_key, 8);
+		condlog (3, "%s: reservation key set.", mpp->wwid);
+	}
+
+	status = mpath_prout_common (mpp, MPATH_PROUT_CLEAR_SA,
+				     rq_scope, rq_type, pamp, noisy);
+
+	if (status) {
+		condlog(0, "%s: failed to send CLEAR_SA", mpp->wwid);
+		goto out1;
+	}
+
+	pamp->num_transportid = 1;
+	pptr=pamp->trnptid_list[0];
+
+	for (i = 0; i < num; i++){
+		if (get_be64(mpp->reservation_key) &&
+			memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
+			       &mpp->reservation_key, 8)){
+			/*register with tarnsport id*/
+			memset(pamp, 0, length);
+			pamp->trnptid_list[0] = pptr;
+			memset (pamp->trnptid_list[0], 0, sizeof (struct transportid));
+			memcpy (pamp->sa_key,
+					pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
+			pamp->sa_flags = MPATH_F_SPEC_I_PT_MASK;
+			pamp->num_transportid = 1;
+
+			memcpy (pamp->trnptid_list[0],
+					&pr_buff->prin_descriptor.prin_readfd.descriptors[i]->trnptid,
+					sizeof (struct transportid));
+			status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
+					pamp, noisy);
+
+			pamp->sa_flags = 0;
+			memcpy (pamp->key, pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
+			memset (pamp->sa_key, 0, 8);
+			pamp->num_transportid = 0;
+			status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
+					pamp, noisy);
+		}
+		else
+		{
+			if (get_be64(mpp->reservation_key))
+				found = 1;
+		}
+
+
+	}
+
+	if (found){
+		memset (pamp, 0, length);
+		memcpy (pamp->sa_key, &mpp->reservation_key, 8);
+		memset (pamp->key, 0, 8);
+		status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);
+	}
+
+
+	free(pptr);
+out1:
+	free (pamp);
+out:
+	free (pr_buff);
+	return (status);
+}
+
+int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
+				    int rq_servact, int rq_scope, unsigned int rq_type,
+				    struct prout_param_descriptor *paramp, int noisy)
+{
+	struct multipath *mpp;
+	char *alias;
+	int ret;
+	uint64_t prkey;
+	struct config *conf;
+
+	ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
+	if (ret != MPATH_PR_SUCCESS)
+		return ret;
+
+	conf = get_multipath_config();
+	select_reservation_key(conf, mpp);
+	select_all_tg_pt(conf, mpp);
+	put_multipath_config(conf);
+
+	memcpy(&prkey, paramp->sa_key, 8);
+	if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
+	    (rq_servact == MPATH_PROUT_REG_IGN_SA ||
+	     (rq_servact == MPATH_PROUT_REG_SA &&
+	      (!get_be64(mpp->reservation_key) ||
+	       memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
+		memcpy(&mpp->reservation_key, paramp->sa_key, 8);
+		if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
+				       paramp->sa_flags)) {
+			condlog(0, "%s: failed to set prkey for multipathd.",
+				alias);
+			ret = MPATH_PR_DMMP_ERROR;
+			goto out1;
+		}
+	}
+
+	if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
+	    memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
+	    (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
+		condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
+		ret = MPATH_PR_SYNTAX_ERROR;
+		goto out1;
+	}
+
+	switch(rq_servact)
+	{
+	case MPATH_PROUT_REG_SA:
+	case MPATH_PROUT_REG_IGN_SA:
+		ret= mpath_prout_reg(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
+		break;
+	case MPATH_PROUT_RES_SA :
+	case MPATH_PROUT_PREE_SA :
+	case MPATH_PROUT_PREE_AB_SA :
+	case MPATH_PROUT_CLEAR_SA:
+		ret = mpath_prout_common(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
+		break;
+	case MPATH_PROUT_REL_SA:
+		ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
+		break;
+	default:
+		ret = MPATH_PR_OTHER;
+		goto out1;
+	}
+
+	if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
+				(rq_servact ==  MPATH_PROUT_REG_IGN_SA)))
+	{
+		if (prkey == 0) {
+			update_prflag(alias, 0);
+			update_prkey(alias, 0);
+		} else
+			update_prflag(alias, 1);
+	} else if ((ret == MPATH_PR_SUCCESS) && (rq_servact == MPATH_PROUT_CLEAR_SA)) {
+		update_prflag(alias, 0);
+		update_prkey(alias, 0);
+	}
+out1:
+	free(alias);
+	return ret;
+}
+
+int update_map_pr(struct multipath *mpp)
+{
+	int noisy=0;
+	struct prin_resp *resp;
+	unsigned int i;
+	int ret, isFound;
+
+	if (!get_be64(mpp->reservation_key))
+	{
+		/* Nothing to do. Assuming pr mgmt feature is disabled*/
+		condlog(4, "%s: reservation_key not set in multipath.conf",
+			mpp->alias);
+		return MPATH_PR_SUCCESS;
+	}
+
+	resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
+	if (!resp)
+	{
+		condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
+		return MPATH_PR_OTHER;
+	}
+	ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
+
+	if (ret != MPATH_PR_SUCCESS )
+	{
+		condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
+		free(resp);
+		return  ret;
+	}
+
+	if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
+	{
+		condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
+		free(resp);
+		return MPATH_PR_SUCCESS;
+	}
+
+	condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias,
+		get_be64(mpp->reservation_key));
+
+	isFound =0;
+	for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
+	{
+		condlog(2, "%s: PR IN READKEYS[%d]  reservation key:", mpp->alias, i);
+		dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
+
+		if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
+		{
+			condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
+			isFound =1;
+		}
+	}
+
+	if (isFound)
+	{
+		mpp->prflag = 1;
+		condlog(2, "%s: prflag flag set.", mpp->alias );
+	}
+
+	free(resp);
+	return MPATH_PR_SUCCESS;
+}
diff --git a/libmpathpersist/mpath_persist_int.h b/libmpathpersist/mpath_persist_int.h
new file mode 100644
index 0000000..58d9c33
--- /dev/null
+++ b/libmpathpersist/mpath_persist_int.h
@@ -0,0 +1,17 @@
+#ifndef _MPATH_PERSIST_INT_H
+#define _MPATH_PERSIST_INT_H
+
+struct multipath;
+
+void * mpath_alloc_prin_response(int prin_sa);
+int do_mpath_persistent_reserve_in(vector curmp, vector pathvec,
+				   int fd, int rq_servact,
+				   struct prin_resp *resp, int noisy);
+void *mpath_alloc_prin_response(int prin_sa);
+int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
+				    int rq_servact, int rq_scope,
+				    unsigned int rq_type,
+				    struct prout_param_descriptor *paramp,
+				    int noisy);
+
+#endif /* _MPATH_PERSIST_INT_H */
diff --git a/libmpathpersist/mpathpr.h b/libmpathpersist/mpathpr.h
index 5ea8cd6..59411e6 100644
--- a/libmpathpersist/mpathpr.h
+++ b/libmpathpersist/mpathpr.h
@@ -31,20 +31,8 @@ int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int
 int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope,
 		unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
 void * _mpath_pr_update (void *arg);
-int mpath_send_prin_activepath (char * dev, int rq_servact, struct prin_resp * resp, int noisy);
-int get_mpvec (vector curmp, vector pathvec, char * refwwid);
-void * mpath_prout_pthread_fn(void *p);
 void dumpHex(const char* , int len, int no_ascii);
 
-int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type,  struct prout_param_descriptor * paramp, int noisy);
-int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type,  struct prout_param_descriptor * paramp, int noisy);
-int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
-	unsigned int rq_type,  struct prout_param_descriptor * paramp, int noisy);
-int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
-	unsigned int rq_type,   struct prout_param_descriptor * paramp, int noisy);
-
 int update_prflag(char *mapname, int set);
 int update_prkey_flags(char *mapname, uint64_t prkey, uint8_t sa_flags);
 #define update_prkey(mapname, prkey) update_prkey_flags(mapname, prkey, 0)
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
index 14245cc..4bdd55c 100644
--- a/mpathpersist/main.c
+++ b/mpathpersist/main.c
@@ -10,6 +10,7 @@
 #include <getopt.h>
 #include <libudev.h>
 #include "mpath_persist.h"
+#include "mpath_persist_int.h"
 #include "main.h"
 #include "debug.h"
 #include <pthread.h>
diff --git a/multipathd/main.c b/multipathd/main.c
index 7a57a79..1db34ac 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -66,6 +66,7 @@
 
 #include "mpath_cmd.h"
 #include "mpath_persist.h"
+#include "mpath_persist_int.h"
 
 #include "prioritizers/alua_rtpg.h"
 
-- 
2.34.1





More information about the dm-devel mailing list