multipath: Fix warnings from stricter compile options.
[multipath-tools/.git] / libmpathpersist / mpath_persist.c
1 #include "mpath_persist.h"
2 #include <libdevmapper.h>
3 #include <defaults.h>
4 #include <sys/stat.h>
5 #include <linux/kdev_t.h>
6 #include <fcntl.h>
7 #include <vector.h>
8 #include <checkers.h>
9 #include <structs.h>
10 #include <structs_vec.h>
11
12 #include <prio.h>
13 #include <unistd.h>
14 #include <devmapper.h>
15 #include <debug.h>
16 #include <config.h>
17 #include <switchgroup.h>
18 #include <discovery.h>
19 #include <dmparser.h>
20 #include <ctype.h>
21 #include <propsel.h>
22
23 #include "mpathpr.h"
24 #include "mpath_pr_ioctl.h"
25
26 #include <pthread.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define __STDC_FORMAT_MACROS 1
32
33
34 int
35 mpath_lib_init (void)
36 {
37         if (load_config(DEFAULT_CONFIGFILE)){
38                 condlog(0, "Failed to initialize multipath config.");
39                 return 1;
40         }
41
42         return 0;
43 }
44
45 int
46 mpath_lib_exit (void)
47 {
48         dm_lib_release();
49         dm_lib_exit();
50         cleanup_prio();
51         cleanup_checkers();
52         free_config(conf);
53         conf = NULL;
54         return 0;
55 }
56
57 static int
58 updatepaths (struct multipath * mpp)
59 {
60         int i, j;
61         struct pathgroup * pgp;
62         struct path * pp;
63
64         if (!mpp->pg)
65                 return 0;
66
67         vector_foreach_slot (mpp->pg, pgp, i){
68                 if (!pgp->paths)
69                         continue;
70
71                 vector_foreach_slot (pgp->paths, pp, j){
72                         if (!strlen(pp->dev)){
73                                 if (devt2devname(pp->dev, pp->dev_t)){
74                                         /*
75                                          * path is not in sysfs anymore
76                                          */
77                                         pp->state = PATH_DOWN;
78                                         continue;
79                                 }
80                                 pp->mpp = mpp;
81                                 pathinfo(pp, conf->hwtable, DI_ALL);
82                                 continue;
83                         }
84                         pp->mpp = mpp;
85                         if (pp->state == PATH_UNCHECKED ||
86                                         pp->state == PATH_WILD)
87                                 pathinfo(pp, conf->hwtable, DI_CHECKER);
88
89                         if (pp->priority == PRIO_UNDEF)
90                                 pathinfo(pp, conf->hwtable, DI_PRIO);
91                 }
92         }
93         return 0;
94 }
95
96 int 
97 mpath_prin_activepath (struct multipath *mpp, int rq_servact,
98         struct prin_resp * resp, int noisy)
99 {
100         int i,j, ret = MPATH_PR_DMMP_ERROR;
101         struct pathgroup *pgp = NULL;
102         struct path *pp = NULL;
103
104         vector_foreach_slot (mpp->pg, pgp, j){
105                 vector_foreach_slot (pgp->paths, pp, i){
106                         if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
107                                 condlog(2, "%s: %s not available. Skip.", mpp->wwid, pp->dev);
108                                 condlog(3, "%s: status = %d.", mpp->wwid, pp->state);
109                                 continue;
110                         }
111
112                         condlog(3, "%s: sending pr in command to %s ", mpp->wwid, pp->dev);
113                         ret = mpath_send_prin_activepath(pp->dev, rq_servact, resp, noisy);
114                         switch(ret)
115                         {
116                                 case MPATH_PR_SUCCESS:
117                                 case MPATH_PR_SENSE_INVALID_OP:
118                                         return ret;
119                                 default:
120                                         continue;
121                         }
122                 }
123         }
124         return ret;     
125 }
126
127 int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp *resp, int noisy, int verbose)
128 {
129         struct stat info;
130         vector curmp = NULL;
131         vector pathvec = NULL;
132         char * alias;
133         struct multipath * mpp;
134         int map_present;
135         int major, minor;
136         int ret;
137
138         conf->verbosity = verbose;
139
140         if (fstat( fd, &info) != 0){
141                 condlog(0, "stat error %d", fd);
142                 return MPATH_PR_FILE_ERROR;
143         } 
144         if(!S_ISBLK(info.st_mode)){
145                 condlog(0, "Failed to get major:minor. fd = %d", fd);
146                 return MPATH_PR_FILE_ERROR;
147         }
148
149         major = (int)MAJOR(info.st_rdev);
150         minor = (int)MINOR(info.st_rdev);       
151         condlog(4, "Device %d:%d:  ", major, minor);
152
153         /* get alias from major:minor*/
154         alias = dm_mapname(major, minor);
155         if (!alias){
156                 condlog(0, "%d:%d failed to get device alias.", major, minor);
157                 return MPATH_PR_DMMP_ERROR;
158         }
159
160         condlog(3, "alias = %s", alias);
161         map_present = dm_map_present(alias);
162         if (map_present && dm_type(alias, TGT_MPATH) <= 0){
163                 condlog( 0, "%s: not a multipath device.", alias);
164                 ret = MPATH_PR_DMMP_ERROR;
165                 goto out;
166         }
167
168         /*
169          * allocate core vectors to store paths and multipaths
170          */
171         curmp = vector_alloc ();
172         pathvec = vector_alloc ();
173
174         if (!curmp || !pathvec){
175                 condlog (0, "%s: vector allocation failed.", alias);
176                 ret = MPATH_PR_DMMP_ERROR;
177                 goto out;
178         }
179
180         if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
181                 ret = MPATH_PR_DMMP_ERROR;
182                 goto out1;
183         }
184
185         /* get info of all paths from the dm device     */
186         if (get_mpvec (curmp, pathvec, alias)){
187                 condlog(0, "%s: failed to get device info.", alias);
188                 ret = MPATH_PR_DMMP_ERROR;
189                 goto out1;
190         }
191
192         mpp = find_mp_by_alias(curmp, alias);
193         if (!mpp){
194                 condlog(0, "%s: devmap not registered.", alias);
195                 ret = MPATH_PR_DMMP_ERROR;
196                 goto out1;
197         }
198
199         ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
200
201 out1:
202         free_multipathvec(curmp, KEEP_PATHS);
203         free_pathvec(pathvec, FREE_PATHS);      
204 out:
205         FREE(alias);
206         return ret;                                             
207 }
208
209 int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
210                 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
211 {
212
213         struct stat info;
214
215         vector curmp = NULL;
216         vector pathvec = NULL;
217
218         char * alias;
219         struct multipath * mpp;
220         int map_present;
221         int major, minor;
222         int ret;
223         int j;
224         unsigned char *keyp;
225         uint64_t prkey;         
226
227         conf->verbosity = verbose;
228
229         if (fstat( fd, &info) != 0){
230                 condlog(0, "stat error fd=%d", fd);
231                 return MPATH_PR_FILE_ERROR;
232         }
233
234         if(!S_ISBLK(info.st_mode)){
235                 condlog(3, "Failed to get major:minor. fd=%d", fd);
236                 return MPATH_PR_FILE_ERROR;     
237         }       
238
239         major = (int)MAJOR(info.st_rdev);
240         minor = (int)MINOR(info.st_rdev);
241         condlog(4, "Device  %d:%d", major, minor);
242
243         /* get WWN of the device from major:minor*/
244         alias = dm_mapname(major, minor);
245         if (!alias){
246                 return MPATH_PR_DMMP_ERROR;
247         }
248
249         condlog(3, "alias = %s", alias);
250         map_present = dm_map_present(alias);
251
252         if (map_present && dm_type(alias, TGT_MPATH) <= 0){
253                 condlog(3, "%s: not a multipath device.", alias);
254                 ret = MPATH_PR_DMMP_ERROR;
255                 goto out;
256         }
257
258         /*
259          * allocate core vectors to store paths and multipaths
260          */
261         curmp = vector_alloc ();
262         pathvec = vector_alloc ();
263
264          if (!curmp || !pathvec){
265                 condlog (0, "%s: vector allocation failed.", alias);
266                 ret = MPATH_PR_DMMP_ERROR;
267                 goto out;
268         }
269
270         if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
271                 ret = MPATH_PR_DMMP_ERROR;
272                 goto out1;
273         }
274
275         /* get info of all paths from the dm device     */
276         if (get_mpvec(curmp, pathvec, alias)){
277                 condlog(0, "%s: failed to get device info.", alias);
278                 ret = MPATH_PR_DMMP_ERROR;
279                 goto out1;
280         }
281
282         mpp = find_mp_by_alias(curmp, alias);
283
284         if (!mpp) {
285                 condlog(0, "%s: devmap not registered.", alias);
286                 ret = MPATH_PR_DMMP_ERROR;
287                 goto out1;
288         }
289
290         select_reservation_key(mpp);
291
292         switch(rq_servact)
293         {
294                 case MPATH_PROUT_REG_SA: 
295                 case MPATH_PROUT_REG_IGN_SA:  
296                         ret= mpath_prout_reg(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
297                         break;
298                 case MPATH_PROUT_RES_SA :  
299                 case MPATH_PROUT_PREE_SA :  
300                 case MPATH_PROUT_PREE_AB_SA :  
301                 case MPATH_PROUT_CLEAR_SA:  
302                         ret = mpath_prout_common(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
303                         break;
304                 case MPATH_PROUT_REL_SA:
305                         ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
306                         break;
307                 default:
308                         ret = MPATH_PR_OTHER;
309                         goto out1;
310         }
311
312         if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
313                                 (rq_servact ==  MPATH_PROUT_REG_IGN_SA)))
314         {
315                 keyp=paramp->sa_key;
316                 prkey = 0;
317                 for (j = 0; j < 8; ++j) {
318                         if (j > 0)
319                                 prkey <<= 8;
320                         prkey |= *keyp;
321                         ++keyp;
322                 }
323                 if (prkey == 0)
324                         update_prflag(alias, "unset", noisy);
325                 else
326                         update_prflag(alias, "set", noisy);
327         } else {
328                 if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_CLEAR_SA) || 
329                                         (rq_servact == MPATH_PROUT_PREE_AB_SA ))){
330                         update_prflag(alias, "unset", noisy);
331                 }
332         }
333 out1:
334         free_multipathvec(curmp, KEEP_PATHS);
335         free_pathvec(pathvec, FREE_PATHS);
336
337 out:
338         FREE(alias);
339         return ret; 
340 }
341
342 int
343 get_mpvec (vector curmp, vector pathvec, char * refwwid)
344 {
345         int i;
346         struct multipath *mpp;
347         char params[PARAMS_SIZE], status[PARAMS_SIZE];
348
349         if (dm_get_maps (curmp)){
350                 return 1;
351         }
352
353         vector_foreach_slot (curmp, mpp, i){
354                 /*
355                  * discard out of scope maps
356                  */
357                 if (mpp->alias && refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE)){
358                         free_multipath (mpp, KEEP_PATHS);
359                         vector_del_slot (curmp, i);
360                         i--;
361                         continue;
362                 }
363
364                 dm_get_map(mpp->alias, &mpp->size, params);
365                 condlog(3, "params = %s", params);
366                 dm_get_status(mpp->alias, status);
367                 condlog(3, "status = %s", status);
368                 disassemble_map (pathvec, params, mpp);
369                 
370                 /*
371                  * disassemble_map() can add new paths to pathvec.
372                  * If not in "fast list mode", we need to fetch information
373                  * about them
374                  */
375                 updatepaths(mpp);
376                 mpp->bestpg = select_path_group (mpp);
377                 disassemble_status (status, mpp);
378
379         }
380         return MPATH_PR_SUCCESS ;
381 }
382
383 void * mpath_prin_pthread_fn (void *p)
384 {
385         int ret;
386         struct prin_param * pparam = (struct prin_param *)p;
387
388         ret = prin_do_scsi_ioctl(pparam->dev, pparam->rq_servact, pparam->resp,  pparam->noisy);
389         pparam->status = ret;   
390         pthread_exit(NULL);     
391 }
392
393 int mpath_send_prin_activepath (char * dev, int rq_servact, struct prin_resp * resp, int noisy)
394 {
395
396         int rc;
397
398         rc = prin_do_scsi_ioctl(dev, rq_servact, resp,  noisy);
399         
400         return (rc);
401 }
402
403 int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
404         unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
405 {
406
407         int i, j;
408         struct pathgroup *pgp = NULL;
409         struct path *pp = NULL;
410         int rollback = 0;
411         int active_pathcount=0; 
412         int rc;
413         int count=0;
414         int status = MPATH_PR_SUCCESS;
415         uint64_t sa_key = 0;
416
417         if (!mpp)
418                 return MPATH_PR_DMMP_ERROR; 
419
420         active_pathcount = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
421
422         if (active_pathcount == 0) {
423                 condlog (0, "%s: no path available", mpp->wwid);
424                 return MPATH_PR_DMMP_ERROR;
425         }
426
427         if ( paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK ) {
428                 condlog (1, "Warning: ALL_TG_PT is set. Configuration not supported");
429         }
430
431         struct threadinfo thread[active_pathcount];
432
433         memset(thread, 0, sizeof(thread));
434
435         /* init thread parameter */
436         for (i =0; i< active_pathcount; i++){
437                 thread[i].param.rq_servact = rq_servact;
438                 thread[i].param.rq_scope = rq_scope;
439                 thread[i].param.rq_type = rq_type;
440                 thread[i].param.paramp = paramp;
441                 thread[i].param.noisy = noisy;
442                 thread[i].param.status = -1;
443
444                 condlog (3, "THRED ID [%d] INFO]", i);
445                 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
446                 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope); 
447                 condlog (3, "rq_type=%d ", thread[i].param.rq_type);  
448                 condlog (3, "rkey="); 
449                 condlog (3, "paramp->sa_flags =%02x ", thread[i].param.paramp->sa_flags); 
450                 condlog (3, "noisy=%d ", thread[i].param.noisy); 
451                 condlog (3, "status=%d ", thread[i].param.status); 
452         }
453
454         pthread_attr_t attr;
455         pthread_attr_init(&attr);
456         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
457
458         vector_foreach_slot (mpp->pg, pgp, j){
459                 vector_foreach_slot (pgp->paths, pp, i){
460                         if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
461                                 condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
462                                 continue;
463                         }
464                         strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
465
466                         if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
467                                 /*
468                                  * Clearing SPEC_I_PT as transportids are already registered by now.
469                                  */
470                                 thread[count].param.paramp->sa_flags &= (~MPATH_F_SPEC_I_PT_MASK);
471                         }
472
473                         condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
474
475                         rc = pthread_create(&thread[count].id, &attr, mpath_prout_pthread_fn, (void *)(&thread[count].param));
476                         if (rc){
477                                 condlog (0, "%s: failed to create thread %d", mpp->wwid, rc);
478                         }
479                         count = count +1;
480                 }
481         }
482         for( i=0; i < active_pathcount ; i++){
483                 rc = pthread_join(thread[i].id, NULL);
484                 if (rc){
485                         condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
486                 }
487                 if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){
488                         rollback = 1;
489                         sa_key = 0;
490                         for (i = 0; i < 8; ++i){
491                                 if (i > 0)
492                                         sa_key <<= 8;
493                                 sa_key |= paramp->sa_key[i];
494                         }
495                         status = MPATH_PR_RESERV_CONFLICT ;
496                 }
497                 if (!rollback && (status == MPATH_PR_SUCCESS)){
498                         status = thread[i].param.status;
499                 }
500         }
501         if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
502                 condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
503                 for( i=0 ; i < active_pathcount ; i++){
504                         if((thread[i].param.status == MPATH_PR_SUCCESS) &&
505                                         ((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
506                                 memcpy(&thread[i].param.paramp->key, &thread[i].param.paramp->sa_key, 8);
507                                 memset(&thread[i].param.paramp->sa_key, 0, 8);
508                                 thread[i].param.status = MPATH_PR_SUCCESS;
509                                 rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn, 
510                                                 (void *)(&thread[count].param));
511                                 if (rc){
512                                         condlog (0, "%s: failed to create thread for rollback. %d",  mpp->wwid, rc);
513                                 }
514                         }
515                 }
516                 for(i=0; i < active_pathcount ; i++){
517                         rc = pthread_join(thread[i].id, NULL);
518                         if (rc){
519                                 condlog (3, "%s: failed to join thread while rolling back %d",
520                                                 mpp->wwid, i);
521                         }
522                 }
523         }
524
525         pthread_attr_destroy(&attr);
526         return (status);
527 }
528
529 void * mpath_prout_pthread_fn(void *p)
530 {
531         int ret;
532         struct prout_param * param = (struct prout_param *)p;
533
534         ret = prout_do_scsi_ioctl( param->dev,param->rq_servact, param->rq_scope,
535                         param->rq_type, param->paramp, param->noisy);
536         param->status = ret;
537         pthread_exit(NULL);
538 }
539
540 int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
541         unsigned int rq_type, struct prout_param_descriptor* paramp, int noisy)
542 {
543         int i,j, ret;
544         struct pathgroup *pgp = NULL;
545         struct path *pp = NULL;
546
547         vector_foreach_slot (mpp->pg, pgp, j){
548                 vector_foreach_slot (pgp->paths, pp, i){
549                         if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
550                                 condlog (1, "%s: %s path not up. Skip", mpp->wwid, pp->dev); 
551                                 continue;
552                         }
553
554                         condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
555                         ret = send_prout_activepath(pp->dev, rq_servact, rq_scope, rq_type, 
556                                         paramp, noisy); 
557                         return ret ;
558                 }
559         }
560         return MPATH_PR_SUCCESS;
561 }
562
563 int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
564         unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
565 {
566         struct prout_param param;
567         param.rq_servact = rq_servact;
568         param.rq_scope  = rq_scope;
569         param.rq_type   = rq_type;
570         param.paramp    = paramp;
571         param.noisy = noisy;
572         param.status = -1;
573
574         pthread_t thread;
575         pthread_attr_t attr;
576         int rc;
577
578         memset(&thread, 0, sizeof(thread));
579         strncpy(param.dev, dev, FILE_NAME_SIZE);
580         /* Initialize and set thread joinable attribute */
581         pthread_attr_init(&attr);
582         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
583
584         rc = pthread_create(&thread, &attr, mpath_prout_pthread_fn, (void *)(&param));
585         if (rc){
586                 condlog (3, "%s: failed to create thread %d", dev, rc);
587                 exit(-1);
588         }
589         /* Free attribute and wait for the other threads */
590         pthread_attr_destroy(&attr);
591         rc = pthread_join(thread, NULL);
592
593         return (param.status);
594 }
595
596 int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
597         unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
598 {
599         int i, j;
600         int num = 0;
601         struct pathgroup *pgp = NULL;
602         struct path *pp = NULL;
603         int active_pathcount = 0;
604         pthread_attr_t attr;
605         int rc, found = 0;;
606         int count = 0;
607         int status = MPATH_PR_SUCCESS;
608         struct prin_resp resp;
609         struct prout_param_descriptor *pamp;
610         struct prin_resp *pr_buff;
611         int length;
612         struct transportid *pptr;       
613
614         if (!mpp)
615                 return MPATH_PR_DMMP_ERROR;
616
617         active_pathcount = pathcount (mpp, PATH_UP) + pathcount (mpp, PATH_GHOST);
618
619         struct threadinfo thread[active_pathcount];
620         memset(thread, 0, sizeof(thread));
621         for (i = 0; i < active_pathcount; i++){
622                 thread[i].param.rq_servact = rq_servact;
623                 thread[i].param.rq_scope = rq_scope;
624                 thread[i].param.rq_type = rq_type;
625                 thread[i].param.paramp = paramp;
626                 thread[i].param.noisy = noisy;
627                 thread[i].param.status = -1;
628
629                 condlog (3, " path count = %d", i);
630                 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
631                 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
632                 condlog (3, "rq_type=%d ", thread[i].param.rq_type);
633                 condlog (3, "noisy=%d ", thread[i].param.noisy);
634                 condlog (3, "status=%d ", thread[i].param.status);
635         }
636
637         pthread_attr_init (&attr);
638         pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
639
640         vector_foreach_slot (mpp->pg, pgp, j){
641                 vector_foreach_slot (pgp->paths, pp, i){
642                         if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
643                                 condlog (1, "%s: %s path not up.", mpp->wwid, pp->dev);
644                                 continue;
645                         }
646                         
647                         strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
648                         condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
649                         rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
650                                         (void *) (&thread[count].param));
651                         if (rc)
652                                 condlog (0, "%s: failed to create thread. %d",  mpp->wwid, rc);
653                         count = count + 1;
654                 }
655         }
656         pthread_attr_destroy (&attr);
657         for (i = 0; i < active_pathcount; i++){
658                 rc = pthread_join (thread[i].id, NULL);
659                 if (rc){
660                         condlog (1, "%s: failed to join thread.  %d",  mpp->wwid,  rc);
661                 }
662         }
663
664         for (i = 0; i < active_pathcount; i++){
665                 /*  check thread status here and return the status */
666
667                 if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
668                         status = MPATH_PR_RESERV_CONFLICT;
669                 else if (status == MPATH_PR_SUCCESS
670                                 && thread[i].param.status != MPATH_PR_RESERV_CONFLICT)
671                         status = thread[i].param.status;
672         }
673
674         status = mpath_prin_activepath (mpp, MPATH_PRIN_RRES_SA, &resp, noisy);
675         if (status != MPATH_PR_SUCCESS){
676                 condlog (0, "%s: pr in read reservation command failed.", mpp->wwid);
677                 return MPATH_PR_OTHER;
678         }
679
680         num = resp.prin_descriptor.prin_readresv.additional_length / 8;
681         if (num == 0){
682                 condlog (2, "%s: Path holding reservation is released.", mpp->wwid);
683                 return MPATH_PR_SUCCESS;        
684         }
685         condlog (2, "%s: Path holding reservation is not avialable.", mpp->wwid);
686
687         pr_buff =  mpath_alloc_prin_response(MPATH_PRIN_RFSTAT_SA);
688         if (!pr_buff){
689                 condlog (0, "%s: failed to  alloc pr in response buffer.", mpp->wwid);  
690                 return MPATH_PR_OTHER;
691         }
692
693         status = mpath_prin_activepath (mpp, MPATH_PRIN_RFSTAT_SA, pr_buff, noisy);
694
695         if (status != MPATH_PR_SUCCESS){
696                 condlog (0,  "%s: pr in read full status command failed.",  mpp->wwid);
697                 goto out;
698         }
699
700         num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
701         if (0 == num){
702                 goto out;
703         }
704         length = sizeof (struct prout_param_descriptor) + (sizeof (struct transportid *));
705
706         pamp = (struct prout_param_descriptor *)malloc (length);
707         if (!pamp){
708                 condlog (0, "%s: failed to alloc pr out parameter.", mpp->wwid);
709                 goto out1;
710         }
711
712         memset(pamp, 0, length);
713
714         pamp->trnptid_list[0] = (struct transportid *) malloc (sizeof (struct transportid));
715         if (!pamp->trnptid_list[0]){
716                 condlog (0, "%s: failed to alloc pr out transportid.", mpp->wwid);
717                 goto out1;
718         }
719
720         if (mpp->reservation_key ){
721                 memcpy (pamp->key, mpp->reservation_key, 8);
722                 condlog (3, "%s: reservation key set.", mpp->wwid);
723         }
724
725         mpath_prout_common (mpp, MPATH_PROUT_CLEAR_SA, rq_scope, rq_type, pamp,
726                         noisy);
727
728         pamp->num_transportid = 1;
729         pptr=pamp->trnptid_list[0];
730
731         for (i = 0; i < num; i++){
732                 if (mpp->reservation_key && 
733                         memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
734                         mpp->reservation_key, 8)){      
735                         /*register with tarnsport id*/
736                         memset(pamp, 0, length);
737                         pamp->trnptid_list[0] = pptr;
738                         memset (pamp->trnptid_list[0], 0, sizeof (struct transportid));
739                         memcpy (pamp->sa_key,
740                                         pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
741                         pamp->sa_flags = MPATH_F_SPEC_I_PT_MASK;
742                         pamp->num_transportid = 1;
743
744                         memcpy (pamp->trnptid_list[0],
745                                         &pr_buff->prin_descriptor.prin_readfd.descriptors[i]->trnptid,
746                                         sizeof (struct transportid));
747                         status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
748                                         pamp, noisy);
749
750                         pamp->sa_flags = 0;
751                         memcpy (pamp->key, pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
752                         memset (pamp->sa_key, 0, 8);
753                         pamp->num_transportid = 0;
754                         status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
755                                         pamp, noisy);
756                 }
757                 else
758                 {
759                         if (mpp->reservation_key)
760                                 found = 1;
761                 }
762
763
764         }
765
766         if (found){
767                 memset (pamp, 0, length);
768                 memcpy (pamp->sa_key, mpp->reservation_key, 8);
769                 memset (pamp->key, 0, 8);
770                 status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);      
771         }
772
773
774         free(pptr);
775 out1:
776         free (pamp);
777 out:
778         free (pr_buff);
779         return (status);
780 }
781
782 void * mpath_alloc_prin_response(int prin_sa)
783 {
784         void * ptr = NULL;
785         int size=0;
786         switch (prin_sa)
787         {
788                 case MPATH_PRIN_RKEY_SA:
789                         size = sizeof(struct prin_readdescr);
790                         ptr = malloc(size);
791                         memset(ptr, 0, size);
792                         break;
793                 case MPATH_PRIN_RRES_SA:
794                         size = sizeof(struct prin_resvdescr);
795                         ptr = malloc(size);
796                         memset(ptr, 0, size);
797                         break;
798                 case MPATH_PRIN_RCAP_SA:
799                         size=sizeof(struct prin_capdescr);
800                         ptr = malloc(size);
801                         memset(ptr, 0, size);
802                         break;
803                 case MPATH_PRIN_RFSTAT_SA:
804                         size = sizeof(struct print_fulldescr_list) + 
805                                 sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
806                         ptr = malloc(size);
807                         memset(ptr, 0, size);
808                         break;
809         }
810         return ptr;
811 }
812
813 int update_map_pr(struct multipath *mpp)
814 {
815         int noisy=0;
816         struct prin_resp *resp;
817         int i,j, ret, isFound;
818         unsigned char *keyp;
819         uint64_t prkey;
820
821         if (!mpp->reservation_key)
822         {
823                 /* Nothing to do. Assuming pr mgmt feature is disabled*/
824                 condlog(3, "%s: reservation_key not set in multiapth.conf", mpp->alias);
825                 return MPATH_PR_SUCCESS;
826         }
827
828         resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
829         if (!resp)
830         {
831                 condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
832                 return MPATH_PR_OTHER;
833         }
834         ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
835
836         if (ret != MPATH_PR_SUCCESS )
837         {
838                 condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
839                 free(resp);
840                 return  ret;
841         }
842
843         if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
844         {
845                 condlog(0,"%s: No key found. Device may not be registered. ", mpp->alias);
846                 free(resp);
847                 return MPATH_PR_SUCCESS;
848         }
849
850         prkey = 0;
851         keyp = mpp->reservation_key;
852         for (j = 0; j < 8; ++j) {
853                 if (j > 0)
854                         prkey <<= 8;
855                 prkey |= *keyp;
856                 ++keyp;
857         }
858         condlog(2, "%s: Multipath  reservation_key: 0x%" PRIx64 " ", mpp->alias, prkey);
859
860         isFound =0;
861         for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
862         {
863                 condlog(2, "%s: PR IN READKEYS[%d]  reservation key:", mpp->alias, i);
864                 dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
865
866                 if (!memcmp(mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
867                 {
868                         condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
869                         isFound =1;
870                 }
871         }
872
873         if (isFound)
874         {
875                 mpp->prflag = 1;
876                 condlog(2, "%s: prflag flag set.", mpp->alias );
877         }
878
879         free(resp);
880         return MPATH_PR_SUCCESS;
881 }
882
883
884