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