libmpathpersist: factor out initialization and teardown
[multipath-tools/.git] / libmpathpersist / mpath_persist.c
index 7a2249f..ce72da6 100644 (file)
@@ -1,25 +1,27 @@
 #include <libdevmapper.h>
-#include <defaults.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 "vector.h"
+#include "checkers.h"
+#include "structs.h"
+#include "structs_vec.h"
 #include <libudev.h>
 
-#include <prio.h>
+#include "prio.h"
 #include <unistd.h>
-#include <devmapper.h>
-#include <debug.h>
-#include <config.h>
-#include <switchgroup.h>
-#include <discovery.h>
-#include <dmparser.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 "propsel.h"
+#include "util.h"
+#include "unaligned.h"
 
 #include "mpath_persist.h"
 #include "mpathpr.h"
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/resource.h>
 
 #define __STDC_FORMAT_MACROS 1
 
+extern struct udev *udev;
 
-int
-mpath_lib_init (struct udev *udev)
+struct config *
+mpath_lib_init (void)
 {
-       if (load_config(DEFAULT_CONFIGFILE, udev)){
+       struct config *conf;
+
+       conf = load_config(DEFAULT_CONFIGFILE);
+       if (!conf) {
                condlog(0, "Failed to initialize multipath config.");
-               return 1;
+               return NULL;
        }
 
-       if (conf->max_fds) {
-               struct rlimit fd_limit;
-
-               fd_limit.rlim_cur = conf->max_fds;
-               fd_limit.rlim_max = conf->max_fds;
-               if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
-                       condlog(0, "can't set open fds limit to %d : %s",
-                                  conf->max_fds, strerror(errno));
-       }
+       set_max_fds(conf->max_fds);
 
-       return 0;
+       return conf;
 }
 
 int
-mpath_lib_exit (void)
+mpath_lib_exit (struct config *conf)
 {
        dm_lib_release();
        dm_lib_exit();
@@ -74,6 +71,7 @@ updatepaths (struct multipath * mpp)
        int i, j;
        struct pathgroup * pgp;
        struct path * pp;
+       struct config *conf;
 
        if (!mpp->pg)
                return 0;
@@ -84,7 +82,7 @@ updatepaths (struct multipath * mpp)
 
                vector_foreach_slot (pgp->paths, pp, j){
                        if (!strlen(pp->dev)){
-                               if (devt2devname(pp->dev, PATH_SIZE,
+                               if (devt2devname(pp->dev, FILE_NAME_SIZE,
                                                 pp->dev_t)){
                                        /*
                                         * path is not in sysfs anymore
@@ -93,16 +91,35 @@ updatepaths (struct multipath * mpp)
                                        continue;
                                }
                                pp->mpp = mpp;
-                               pathinfo(pp, conf->hwtable, DI_ALL);
+                               conf = get_multipath_config();
+                               pathinfo(pp, conf, DI_ALL);
+                               put_multipath_config(conf);
                                continue;
                        }
                        pp->mpp = mpp;
+                       if (pp->udev == NULL) {
+                               pp->udev = get_udev_device(pp->dev_t, DEV_DEVT);
+                               if (pp->udev == NULL) {
+                                       pp->state = PATH_DOWN;
+                                       continue;
+                               }
+                               conf = get_multipath_config();
+                               pathinfo(pp, conf, DI_SYSFS|DI_CHECKER);
+                               put_multipath_config(conf);
+                               continue;
+                       }
                        if (pp->state == PATH_UNCHECKED ||
-                                       pp->state == PATH_WILD)
-                               pathinfo(pp, conf->hwtable, DI_CHECKER);
+                                       pp->state == PATH_WILD) {
+                               conf = get_multipath_config();
+                               pathinfo(pp, conf, DI_CHECKER);
+                               put_multipath_config(conf);
+                       }
 
-                       if (pp->priority == PRIO_UNDEF)
-                               pathinfo(pp, conf->hwtable, DI_PRIO);
+                       if (pp->priority == PRIO_UNDEF) {
+                               conf = get_multipath_config();
+                               pathinfo(pp, conf, DI_PRIO);
+                               put_multipath_config(conf);
+                       }
                }
        }
        return 0;
@@ -147,45 +164,47 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact,
 int mpath_persistent_reserve_in (int fd, int rq_servact,
        struct prin_resp *resp, int noisy, int verbose)
 {
-       struct stat info;
-       vector curmp = NULL;
-       vector pathvec = NULL;
-       char * alias;
-       struct multipath * mpp;
-       int map_present;
-       int major, minor;
-       int ret;
+       int ret = mpath_persistent_reserve_init_vecs(verbose);
 
-       conf->verbosity = verbose;
+       if (ret != MPATH_PR_SUCCESS)
+               return ret;
+       ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy);
+       mpath_persistent_reserve_free_vecs();
+       return ret;
+}
 
-       if (fstat( fd, &info) != 0){
-               condlog(0, "stat error %d", fd);
-               return MPATH_PR_FILE_ERROR;
-       }
-       if(!S_ISBLK(info.st_mode)){
-               condlog(0, "Failed to get major:minor. fd = %d", fd);
-               return MPATH_PR_FILE_ERROR;
-       }
+int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
+       unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
+{
+       int ret = mpath_persistent_reserve_init_vecs(verbose);
 
-       major = major(info.st_rdev);
-       minor = minor(info.st_rdev);
-       condlog(4, "Device %d:%d:  ", major, minor);
+       if (ret != MPATH_PR_SUCCESS)
+               return ret;
+       ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
+                                            paramp, noisy);
+       mpath_persistent_reserve_free_vecs();
+       return ret;
+}
 
-       /* 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;
-       }
+static vector curmp;
+static vector pathvec;
 
-       condlog(3, "alias = %s", alias);
-       map_present = dm_map_present(alias);
-       if (map_present && !dm_is_mpath(alias)){
-               condlog( 0, "%s: not a multipath device.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out;
-       }
+void mpath_persistent_reserve_free_vecs(void)
+{
+       free_multipathvec(curmp, KEEP_PATHS);
+       free_pathvec(pathvec, FREE_PATHS);
+       curmp = pathvec = NULL;
+}
 
+int mpath_persistent_reserve_init_vecs(int verbose)
+{
+       struct config *conf = get_multipath_config();
+
+       conf->verbosity = verbose;
+       put_multipath_config(conf);
+
+       if (curmp)
+               return MPATH_PR_SUCCESS;
        /*
         * allocate core vectors to store paths and multipaths
         */
@@ -193,65 +212,32 @@ int mpath_persistent_reserve_in (int fd, int rq_servact,
        pathvec = vector_alloc ();
 
        if (!curmp || !pathvec){
-               condlog (0, "%s: vector allocation failed.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out;
-       }
-
-       if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) {
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
-       }
-
-       /* get info of all paths from the dm device     */
-       if (get_mpvec (curmp, pathvec, alias)){
-               condlog(0, "%s: failed to get device info.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
+               condlog (0, "vector allocation failed.");
+               goto err;
        }
 
-       mpp = find_mp_by_alias(curmp, alias);
-       if (!mpp){
-               condlog(0, "%s: devmap not registered.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
-       }
+       if (dm_get_maps(curmp))
+               goto err;
 
-       ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
+       return MPATH_PR_SUCCESS;
 
-out1:
-       free_multipathvec(curmp, KEEP_PATHS);
-       free_pathvec(pathvec, FREE_PATHS);
-out:
-       FREE(alias);
-       return ret;
+err:
+       mpath_persistent_reserve_free_vecs();
+       return MPATH_PR_DMMP_ERROR;
 }
 
-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
-       unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
+static int mpath_get_map(int fd, char **palias, struct multipath **pmpp)
 {
-
+       int ret = MPATH_PR_DMMP_ERROR;
        struct stat info;
-
-       vector curmp = NULL;
-       vector pathvec = NULL;
-
-       char * alias;
-       struct multipath * mpp;
-       int map_present;
        int major, minor;
-       int ret;
-       int j;
-       unsigned char *keyp;
-       uint64_t prkey;
-
-       conf->verbosity = verbose;
+       char *alias;
+       struct multipath *mpp;
 
-       if (fstat( fd, &info) != 0){
+       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;
@@ -261,54 +247,99 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
        minor = minor(info.st_rdev);
        condlog(4, "Device  %d:%d", major, minor);
 
-       /* get WWN of the device from 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);
-       map_present = dm_map_present(alias);
 
-       if (map_present && !dm_is_mpath(alias)){
+       if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
                condlog(3, "%s: not a multipath device.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
                goto out;
        }
 
-       /*
-        * allocate core vectors to store paths and multipaths
-        */
-       curmp = vector_alloc ();
-       pathvec = vector_alloc ();
-
-       if (!curmp || !pathvec){
-               condlog (0, "%s: vector allocation failed.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out;
-       }
-
-       if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) {
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
-       }
-
        /* get info of all paths from the dm device     */
        if (get_mpvec(curmp, pathvec, alias)){
                condlog(0, "%s: failed to get device info.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
+               goto out;
        }
 
        mpp = find_mp_by_alias(curmp, alias);
 
        if (!mpp) {
                condlog(0, "%s: devmap not registered.", alias);
-               ret = MPATH_PR_DMMP_ERROR;
-               goto out1;
+               goto out;
+       }
+
+       ret = MPATH_PR_SUCCESS;
+       if (pmpp)
+               *pmpp = mpp;
+       if (palias) {
+               *palias = alias;
+               alias = NULL;
        }
+out:
+       FREE(alias);
+       return ret;
+}
+
+int __mpath_persistent_reserve_in (int fd, int rq_servact,
+       struct prin_resp *resp, int noisy)
+{
+       struct multipath *mpp;
+       int ret;
 
-       select_reservation_key(mpp);
+       ret = mpath_get_map(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_out ( 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(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 &&
+           ((!get_be64(mpp->reservation_key) &&
+             rq_servact == MPATH_PROUT_REG_SA) ||
+            rq_servact == MPATH_PROUT_REG_IGN_SA)) {
+               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)) {
+               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)
        {
@@ -333,29 +364,16 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
        if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
                                (rq_servact ==  MPATH_PROUT_REG_IGN_SA)))
        {
-               keyp=paramp->sa_key;
-               prkey = 0;
-               for (j = 0; j < 8; ++j) {
-                       if (j > 0)
-                               prkey <<= 8;
-                       prkey |= *keyp;
-                       ++keyp;
-               }
-               if (prkey == 0)
-                       update_prflag(alias, "unset", noisy);
-               else
-                       update_prflag(alias, "set", noisy);
-       } else {
-               if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_CLEAR_SA) ||
-                                       (rq_servact == MPATH_PROUT_PREE_AB_SA ))){
-                       update_prflag(alias, "unset", noisy);
-               }
+               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_multipathvec(curmp, KEEP_PATHS);
-       free_pathvec(pathvec, FREE_PATHS);
-
-out:
        FREE(alias);
        return ret;
 }
@@ -367,26 +385,27 @@ get_mpvec (vector curmp, vector pathvec, char * refwwid)
        struct multipath *mpp;
        char params[PARAMS_SIZE], status[PARAMS_SIZE];
 
-       if (dm_get_maps (curmp)){
-               return 1;
-       }
-
        vector_foreach_slot (curmp, mpp, i){
                /*
                 * discard out of scope maps
                 */
-               if (mpp->alias && refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE)){
-                       free_multipath (mpp, KEEP_PATHS);
-                       vector_del_slot (curmp, i);
-                       i--;
+               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;
+
                dm_get_map(mpp->alias, &mpp->size, params);
                condlog(3, "params = %s", params);
                dm_get_status(mpp->alias, status);
                condlog(3, "status = %s", status);
-               disassemble_map (pathvec, params, mpp);
+               disassemble_map (pathvec, params, mpp, 0);
 
                /*
                 * disassemble_map() can add new paths to pathvec.
@@ -401,17 +420,6 @@ get_mpvec (vector curmp, vector pathvec, char * refwwid)
        return MPATH_PR_SUCCESS ;
 }
 
-void * mpath_prin_pthread_fn (void *p)
-{
-       int ret;
-       struct prin_param * pparam = (struct prin_param *)p;
-
-       ret = prin_do_scsi_ioctl(pparam->dev, pparam->rq_servact,
-                                pparam->resp,  pparam->noisy);
-       pparam->status = ret;
-       pthread_exit(NULL);
-}
-
 int mpath_send_prin_activepath (char * dev, int rq_servact,
                                struct prin_resp * resp, int noisy)
 {
@@ -427,7 +435,7 @@ 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;
+       int i, j, k;
        struct pathgroup *pgp = NULL;
        struct path *pp = NULL;
        int rollback = 0;
@@ -435,11 +443,14 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
        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 = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
 
        if (active_pathcount == 0) {
@@ -447,24 +458,22 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
                return MPATH_PR_DMMP_ERROR;
        }
 
-       if ( paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK ) {
-               condlog (1, "Warning: ALL_TG_PT is set. Configuration not supported");
-       }
-
        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 = -1;
+               thread[i].param.status = MPATH_PR_SKIP;
 
-               condlog (3, "THRED ID [%d] INFO]", i);
+               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);
@@ -485,7 +494,18 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
                                condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
                                continue;
                        }
-                       strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
+                       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;
+                       }
+                       strncpy(thread[count].param.dev, pp->dev,
+                               FILE_NAME_SIZE - 1);
 
                        if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
                                /*
@@ -499,23 +519,23 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
                        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;
+                       else
+                               hosts[count] = pp->sg_id.host_no;
+                       count = count + 1;
                }
        }
-       for( i=0; i < active_pathcount ; i++){
-               rc = pthread_join(thread[i].id, NULL);
-               if (rc){
-                       condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
+       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 = 0;
-                       for (i = 0; i < 8; ++i){
-                               if (i > 0)
-                                       sa_key <<= 8;
-                               sa_key |= paramp->sa_key[i];
-                       }
+                       sa_key = get_unaligned_be64(&paramp->sa_key[0]);
                        status = MPATH_PR_RESERV_CONFLICT ;
                }
                if (!rollback && (status == MPATH_PR_SUCCESS)){
@@ -524,24 +544,27 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
        }
        if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
                condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
-               for( i=0 ; i < active_pathcount ; i++){
-                       if((thread[i].param.status == MPATH_PR_SUCCESS) &&
-                                       ((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
-                               memcpy(&thread[i].param.paramp->key, &thread[i].param.paramp->sa_key, 8);
-                               memset(&thread[i].param.paramp->sa_key, 0, 8);
-                               thread[i].param.status = MPATH_PR_SUCCESS;
-                               rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn, 
+               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 < active_pathcount ; i++){
-                       rc = pthread_join(thread[i].id, NULL);
-                       if (rc){
-                               condlog (3, "%s: failed to join thread while rolling back %d",
-                                               mpp->wwid, i);
+               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);
+                               }
                        }
                }
        }
@@ -602,7 +625,7 @@ int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
        int rc;
 
        memset(&thread, 0, sizeof(thread));
-       strncpy(param.dev, dev, FILE_NAME_SIZE);
+       strncpy(param.dev, dev, FILE_NAME_SIZE - 1);
        /* Initialize and set thread joinable attribute */
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -610,7 +633,7 @@ int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
        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_OTHER;
+               return MPATH_PR_THREAD_ERROR;
        }
        /* Free attribute and wait for the other threads */
        pthread_attr_destroy(&attr);
@@ -628,7 +651,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
        struct path *pp = NULL;
        int active_pathcount = 0;
        pthread_attr_t attr;
-       int rc, found = 0;;
+       int rc, found = 0;
        int count = 0;
        int status = MPATH_PR_SUCCESS;
        struct prin_resp resp;
@@ -650,7 +673,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
                thread[i].param.rq_type = rq_type;
                thread[i].param.paramp = paramp;
                thread[i].param.noisy = noisy;
-               thread[i].param.status = -1;
+               thread[i].param.status = MPATH_PR_SKIP;
 
                condlog (3, " path count = %d", i);
                condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
@@ -670,24 +693,29 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
                                continue;
                        }
 
-                       strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
+                       strncpy(thread[count].param.dev, pp->dev,
+                               FILE_NAME_SIZE - 1);
                        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)
+                       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 < active_pathcount; i++){
-               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++){
+               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 < active_pathcount; i++){
+       for (i = 0; i < count; i++){
                /*  check thread status here and return the status */
 
                if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
@@ -743,8 +771,8 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
                goto out1;
        }
 
-       if (mpp->reservation_key ){
-               memcpy (pamp->key, mpp->reservation_key, 8);
+       if (get_be64(mpp->reservation_key)){
+               memcpy (pamp->key, &mpp->reservation_key, 8);
                condlog (3, "%s: reservation key set.", mpp->wwid);
        }
 
@@ -760,9 +788,9 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
        pptr=pamp->trnptid_list[0];
 
        for (i = 0; i < num; i++){
-               if (mpp->reservation_key &&
+               if (get_be64(mpp->reservation_key) &&
                        memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
-                              mpp->reservation_key, 8)){
+                              &mpp->reservation_key, 8)){
                        /*register with tarnsport id*/
                        memset(pamp, 0, length);
                        pamp->trnptid_list[0] = pptr;
@@ -787,7 +815,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
                }
                else
                {
-                       if (mpp->reservation_key)
+                       if (get_be64(mpp->reservation_key))
                                found = 1;
                }
 
@@ -796,7 +824,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
 
        if (found){
                memset (pamp, 0, length);
-               memcpy (pamp->sa_key, mpp->reservation_key, 8);
+               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);
        }
@@ -818,26 +846,22 @@ void * mpath_alloc_prin_response(int prin_sa)
        {
                case MPATH_PRIN_RKEY_SA:
                        size = sizeof(struct prin_readdescr);
-                       ptr = malloc(size);
-                       memset(ptr, 0, size);
                        break;
                case MPATH_PRIN_RRES_SA:
                        size = sizeof(struct prin_resvdescr);
-                       ptr = malloc(size);
-                       memset(ptr, 0, size);
                        break;
                case MPATH_PRIN_RCAP_SA:
                        size=sizeof(struct prin_capdescr);
-                       ptr = malloc(size);
-                       memset(ptr, 0, size);
                        break;
                case MPATH_PRIN_RFSTAT_SA:
                        size = sizeof(struct print_fulldescr_list) +
                                sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
-                       ptr = malloc(size);
-                       memset(ptr, 0, size);
                        break;
        }
+       if (size > 0)
+       {
+               ptr = calloc(size, 1);
+       }
        return ptr;
 }
 
@@ -845,14 +869,13 @@ int update_map_pr(struct multipath *mpp)
 {
        int noisy=0;
        struct prin_resp *resp;
-       int i,j, ret, isFound;
-       unsigned char *keyp;
-       uint64_t prkey;
+       int i, ret, isFound;
 
-       if (!mpp->reservation_key)
+       if (!get_be64(mpp->reservation_key))
        {
                /* Nothing to do. Assuming pr mgmt feature is disabled*/
-               condlog(3, "%s: reservation_key not set in multiapth.conf", mpp->alias);
+               condlog(4, "%s: reservation_key not set in multipath.conf",
+                       mpp->alias);
                return MPATH_PR_SUCCESS;
        }
 
@@ -873,20 +896,13 @@ int update_map_pr(struct multipath *mpp)
 
        if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
        {
-               condlog(0,"%s: No key found. Device may not be registered. ", mpp->alias);
+               condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
                free(resp);
                return MPATH_PR_SUCCESS;
        }
 
-       prkey = 0;
-       keyp = mpp->reservation_key;
-       for (j = 0; j < 8; ++j) {
-               if (j > 0)
-                       prkey <<= 8;
-               prkey |= *keyp;
-               ++keyp;
-       }
-       condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias, prkey);
+       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++ )
@@ -894,7 +910,7 @@ int update_map_pr(struct multipath *mpp)
                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))
+               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;
@@ -910,6 +926,3 @@ int update_map_pr(struct multipath *mpp)
        free(resp);
        return MPATH_PR_SUCCESS;
 }
-
-
-