1 #include <libdevmapper.h>
9 #include "structs_vec.h"
14 #include "devmapper.h"
17 #include "switchgroup.h"
18 #include "discovery.h"
23 #include "unaligned.h"
25 #include "mpath_persist.h"
27 #include "mpath_pr_ioctl.h"
35 #define __STDC_FORMAT_MACROS 1
37 extern struct udev *udev;
44 conf = load_config(DEFAULT_CONFIGFILE);
46 condlog(0, "Failed to initialize multipath config.");
50 set_max_fds(conf->max_fds);
56 mpath_lib_exit (struct config *conf)
68 updatepaths (struct multipath * mpp)
71 struct pathgroup * pgp;
78 vector_foreach_slot (mpp->pg, pgp, i){
82 vector_foreach_slot (pgp->paths, pp, j){
83 if (!strlen(pp->dev)){
84 if (devt2devname(pp->dev, FILE_NAME_SIZE,
87 * path is not in sysfs anymore
89 pp->state = PATH_DOWN;
93 conf = get_multipath_config();
94 pathinfo(pp, conf, DI_ALL);
95 put_multipath_config(conf);
99 if (pp->state == PATH_UNCHECKED ||
100 pp->state == PATH_WILD) {
101 conf = get_multipath_config();
102 pathinfo(pp, conf, DI_CHECKER);
103 put_multipath_config(conf);
106 if (pp->priority == PRIO_UNDEF) {
107 conf = get_multipath_config();
108 pathinfo(pp, conf, DI_PRIO);
109 put_multipath_config(conf);
117 mpath_prin_activepath (struct multipath *mpp, int rq_servact,
118 struct prin_resp * resp, int noisy)
120 int i,j, ret = MPATH_PR_DMMP_ERROR;
121 struct pathgroup *pgp = NULL;
122 struct path *pp = NULL;
124 vector_foreach_slot (mpp->pg, pgp, j){
125 vector_foreach_slot (pgp->paths, pp, i){
126 if (!((pp->state == PATH_UP) ||
127 (pp->state == PATH_GHOST))){
128 condlog(2, "%s: %s not available. Skip.",
130 condlog(3, "%s: status = %d.",
131 mpp->wwid, pp->state);
135 condlog(3, "%s: sending pr in command to %s ",
137 ret = mpath_send_prin_activepath(pp->dev, rq_servact,
141 case MPATH_PR_SUCCESS:
142 case MPATH_PR_SENSE_INVALID_OP:
152 int mpath_persistent_reserve_in (int fd, int rq_servact,
153 struct prin_resp *resp, int noisy, int verbose)
157 vector pathvec = NULL;
159 struct multipath * mpp;
165 conf = get_multipath_config();
166 conf->verbosity = verbose;
167 put_multipath_config(conf);
169 if (fstat( fd, &info) != 0){
170 condlog(0, "stat error %d", fd);
171 return MPATH_PR_FILE_ERROR;
173 if(!S_ISBLK(info.st_mode)){
174 condlog(0, "Failed to get major:minor. fd = %d", fd);
175 return MPATH_PR_FILE_ERROR;
178 major = major(info.st_rdev);
179 minor = minor(info.st_rdev);
180 condlog(4, "Device %d:%d: ", major, minor);
182 /* get alias from major:minor*/
183 alias = dm_mapname(major, minor);
185 condlog(0, "%d:%d failed to get device alias.", major, minor);
186 return MPATH_PR_DMMP_ERROR;
189 condlog(3, "alias = %s", alias);
190 map_present = dm_map_present(alias);
191 if (map_present && !dm_is_mpath(alias)){
192 condlog( 0, "%s: not a multipath device.", alias);
193 ret = MPATH_PR_DMMP_ERROR;
198 * allocate core vectors to store paths and multipaths
200 curmp = vector_alloc ();
201 pathvec = vector_alloc ();
203 if (!curmp || !pathvec){
204 condlog (0, "%s: vector allocation failed.", alias);
205 ret = MPATH_PR_DMMP_ERROR;
209 vector_free(pathvec);
213 if (path_discovery(pathvec, DI_SYSFS | DI_CHECKER) < 0) {
214 ret = MPATH_PR_DMMP_ERROR;
218 /* get info of all paths from the dm device */
219 if (get_mpvec (curmp, pathvec, alias)){
220 condlog(0, "%s: failed to get device info.", alias);
221 ret = MPATH_PR_DMMP_ERROR;
225 mpp = find_mp_by_alias(curmp, alias);
227 condlog(0, "%s: devmap not registered.", alias);
228 ret = MPATH_PR_DMMP_ERROR;
232 ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
235 free_multipathvec(curmp, KEEP_PATHS);
236 free_pathvec(pathvec, FREE_PATHS);
242 int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
243 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
249 vector pathvec = NULL;
252 struct multipath * mpp;
259 conf = get_multipath_config();
260 conf->verbosity = verbose;
261 put_multipath_config(conf);
263 if (fstat( fd, &info) != 0){
264 condlog(0, "stat error fd=%d", fd);
265 return MPATH_PR_FILE_ERROR;
268 if(!S_ISBLK(info.st_mode)){
269 condlog(3, "Failed to get major:minor. fd=%d", fd);
270 return MPATH_PR_FILE_ERROR;
273 major = major(info.st_rdev);
274 minor = minor(info.st_rdev);
275 condlog(4, "Device %d:%d", major, minor);
277 /* get WWN of the device from major:minor*/
278 alias = dm_mapname(major, minor);
280 return MPATH_PR_DMMP_ERROR;
283 condlog(3, "alias = %s", alias);
284 map_present = dm_map_present(alias);
286 if (map_present && !dm_is_mpath(alias)){
287 condlog(3, "%s: not a multipath device.", alias);
288 ret = MPATH_PR_DMMP_ERROR;
293 * allocate core vectors to store paths and multipaths
295 curmp = vector_alloc ();
296 pathvec = vector_alloc ();
298 if (!curmp || !pathvec){
299 condlog (0, "%s: vector allocation failed.", alias);
300 ret = MPATH_PR_DMMP_ERROR;
304 vector_free(pathvec);
308 if (path_discovery(pathvec, DI_SYSFS | DI_CHECKER) < 0) {
309 ret = MPATH_PR_DMMP_ERROR;
313 /* get info of all paths from the dm device */
314 if (get_mpvec(curmp, pathvec, alias)){
315 condlog(0, "%s: failed to get device info.", alias);
316 ret = MPATH_PR_DMMP_ERROR;
320 mpp = find_mp_by_alias(curmp, alias);
323 condlog(0, "%s: devmap not registered.", alias);
324 ret = MPATH_PR_DMMP_ERROR;
328 conf = get_multipath_config();
329 select_reservation_key(conf, mpp);
330 select_all_tg_pt(conf, mpp);
331 put_multipath_config(conf);
333 memcpy(&prkey, paramp->sa_key, 8);
334 if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
335 ((!get_be64(mpp->reservation_key) &&
336 rq_servact == MPATH_PROUT_REG_SA) ||
337 rq_servact == MPATH_PROUT_REG_IGN_SA)) {
338 memcpy(&mpp->reservation_key, paramp->sa_key, 8);
339 if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
341 condlog(0, "%s: failed to set prkey for multipathd.",
343 ret = MPATH_PR_DMMP_ERROR;
348 if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
349 memcmp(paramp->sa_key, &mpp->reservation_key, 8)) {
350 condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
351 ret = MPATH_PR_SYNTAX_ERROR;
357 case MPATH_PROUT_REG_SA:
358 case MPATH_PROUT_REG_IGN_SA:
359 ret= mpath_prout_reg(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
361 case MPATH_PROUT_RES_SA :
362 case MPATH_PROUT_PREE_SA :
363 case MPATH_PROUT_PREE_AB_SA :
364 case MPATH_PROUT_CLEAR_SA:
365 ret = mpath_prout_common(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
367 case MPATH_PROUT_REL_SA:
368 ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
371 ret = MPATH_PR_OTHER;
375 if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
376 (rq_servact == MPATH_PROUT_REG_IGN_SA)))
379 update_prflag(alias, 0);
380 update_prkey(alias, 0);
382 update_prflag(alias, 1);
383 } else if ((ret == MPATH_PR_SUCCESS) && (rq_servact == MPATH_PROUT_CLEAR_SA)) {
384 update_prflag(alias, 0);
385 update_prkey(alias, 0);
388 free_multipathvec(curmp, KEEP_PATHS);
389 free_pathvec(pathvec, FREE_PATHS);
397 get_mpvec (vector curmp, vector pathvec, char * refwwid)
400 struct multipath *mpp;
401 char params[PARAMS_SIZE], status[PARAMS_SIZE];
403 if (dm_get_maps (curmp)){
407 vector_foreach_slot (curmp, mpp, i){
409 * discard out of scope maps
411 if (mpp->alias && refwwid &&
412 strncmp (mpp->alias, refwwid, WWID_SIZE - 1)){
413 free_multipath (mpp, KEEP_PATHS);
414 vector_del_slot (curmp, i);
419 dm_get_map(mpp->alias, &mpp->size, params);
420 condlog(3, "params = %s", params);
421 dm_get_status(mpp->alias, status);
422 condlog(3, "status = %s", status);
423 disassemble_map (pathvec, params, mpp, 0);
426 * disassemble_map() can add new paths to pathvec.
427 * If not in "fast list mode", we need to fetch information
431 mpp->bestpg = select_path_group (mpp);
432 disassemble_status (status, mpp);
435 return MPATH_PR_SUCCESS ;
438 int mpath_send_prin_activepath (char * dev, int rq_servact,
439 struct prin_resp * resp, int noisy)
444 rc = prin_do_scsi_ioctl(dev, rq_servact, resp, noisy);
449 int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
450 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
454 struct pathgroup *pgp = NULL;
455 struct path *pp = NULL;
457 int active_pathcount=0;
460 int status = MPATH_PR_SUCCESS;
465 return MPATH_PR_DMMP_ERROR;
467 all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON ||
468 paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK);
469 active_pathcount = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
471 if (active_pathcount == 0) {
472 condlog (0, "%s: no path available", mpp->wwid);
473 return MPATH_PR_DMMP_ERROR;
476 struct threadinfo thread[active_pathcount];
477 int hosts[active_pathcount];
479 memset(thread, 0, sizeof(thread));
481 /* init thread parameter */
482 for (i =0; i< active_pathcount; i++){
484 thread[i].param.rq_servact = rq_servact;
485 thread[i].param.rq_scope = rq_scope;
486 thread[i].param.rq_type = rq_type;
487 thread[i].param.paramp = paramp;
488 thread[i].param.noisy = noisy;
489 thread[i].param.status = MPATH_PR_SKIP;
491 condlog (3, "THREAD ID [%d] INFO]", i);
492 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
493 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
494 condlog (3, "rq_type=%d ", thread[i].param.rq_type);
495 condlog (3, "rkey=");
496 condlog (3, "paramp->sa_flags =%02x ",
497 thread[i].param.paramp->sa_flags);
498 condlog (3, "noisy=%d ", thread[i].param.noisy);
499 condlog (3, "status=%d ", thread[i].param.status);
503 pthread_attr_init(&attr);
504 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
506 vector_foreach_slot (mpp->pg, pgp, j){
507 vector_foreach_slot (pgp->paths, pp, i){
508 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
509 condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
512 if (all_tg_pt && pp->sg_id.host_no != -1) {
513 for (k = 0; k < count; k++) {
514 if (pp->sg_id.host_no == hosts[k]) {
515 condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no);
522 strncpy(thread[count].param.dev, pp->dev,
525 if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
527 * Clearing SPEC_I_PT as transportids are already registered by now.
529 thread[count].param.paramp->sa_flags &= (~MPATH_F_SPEC_I_PT_MASK);
532 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
534 rc = pthread_create(&thread[count].id, &attr, mpath_prout_pthread_fn, (void *)(&thread[count].param));
536 condlog (0, "%s: failed to create thread %d", mpp->wwid, rc);
537 thread[count].param.status = MPATH_PR_THREAD_ERROR;
540 hosts[count] = pp->sg_id.host_no;
544 for( i=0; i < count ; i++){
545 if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
546 rc = pthread_join(thread[i].id, NULL);
548 condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
551 if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){
553 sa_key = get_unaligned_be64(¶mp->sa_key[0]);
554 status = MPATH_PR_RESERV_CONFLICT ;
556 if (!rollback && (status == MPATH_PR_SUCCESS)){
557 status = thread[i].param.status;
560 if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
561 condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
562 memcpy(¶mp->key, ¶mp->sa_key, 8);
563 memset(¶mp->sa_key, 0, 8);
564 for( i=0 ; i < count ; i++){
565 if(thread[i].param.status == MPATH_PR_SUCCESS) {
566 rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
567 (void *)(&thread[i].param));
569 condlog (0, "%s: failed to create thread for rollback. %d", mpp->wwid, rc);
570 thread[i].param.status = MPATH_PR_THREAD_ERROR;
573 thread[i].param.status = MPATH_PR_SKIP;
575 for(i=0; i < count ; i++){
576 if (thread[i].param.status != MPATH_PR_SKIP &&
577 thread[i].param.status != MPATH_PR_THREAD_ERROR) {
578 rc = pthread_join(thread[i].id, NULL);
580 condlog (3, "%s: failed to join thread while rolling back %d",
587 pthread_attr_destroy(&attr);
591 void * mpath_prout_pthread_fn(void *p)
594 struct prout_param * param = (struct prout_param *)p;
596 ret = prout_do_scsi_ioctl( param->dev,param->rq_servact, param->rq_scope,
597 param->rq_type, param->paramp, param->noisy);
602 int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
603 unsigned int rq_type, struct prout_param_descriptor* paramp, int noisy)
606 struct pathgroup *pgp = NULL;
607 struct path *pp = NULL;
609 vector_foreach_slot (mpp->pg, pgp, j){
610 vector_foreach_slot (pgp->paths, pp, i){
611 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
612 condlog (1, "%s: %s path not up. Skip",
617 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
618 ret = send_prout_activepath(pp->dev, rq_servact,
624 return MPATH_PR_SUCCESS;
627 int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
628 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
630 struct prout_param param;
631 param.rq_servact = rq_servact;
632 param.rq_scope = rq_scope;
633 param.rq_type = rq_type;
634 param.paramp = paramp;
642 memset(&thread, 0, sizeof(thread));
643 strncpy(param.dev, dev, FILE_NAME_SIZE - 1);
644 /* Initialize and set thread joinable attribute */
645 pthread_attr_init(&attr);
646 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
648 rc = pthread_create(&thread, &attr, mpath_prout_pthread_fn, (void *)(¶m));
650 condlog (3, "%s: failed to create thread %d", dev, rc);
651 return MPATH_PR_THREAD_ERROR;
653 /* Free attribute and wait for the other threads */
654 pthread_attr_destroy(&attr);
655 rc = pthread_join(thread, NULL);
657 return (param.status);
660 int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
661 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
665 struct pathgroup *pgp = NULL;
666 struct path *pp = NULL;
667 int active_pathcount = 0;
671 int status = MPATH_PR_SUCCESS;
672 struct prin_resp resp;
673 struct prout_param_descriptor *pamp;
674 struct prin_resp *pr_buff;
676 struct transportid *pptr;
679 return MPATH_PR_DMMP_ERROR;
681 active_pathcount = pathcount (mpp, PATH_UP) + pathcount (mpp, PATH_GHOST);
683 struct threadinfo thread[active_pathcount];
684 memset(thread, 0, sizeof(thread));
685 for (i = 0; i < active_pathcount; i++){
686 thread[i].param.rq_servact = rq_servact;
687 thread[i].param.rq_scope = rq_scope;
688 thread[i].param.rq_type = rq_type;
689 thread[i].param.paramp = paramp;
690 thread[i].param.noisy = noisy;
691 thread[i].param.status = MPATH_PR_SKIP;
693 condlog (3, " path count = %d", i);
694 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
695 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
696 condlog (3, "rq_type=%d ", thread[i].param.rq_type);
697 condlog (3, "noisy=%d ", thread[i].param.noisy);
698 condlog (3, "status=%d ", thread[i].param.status);
701 pthread_attr_init (&attr);
702 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
704 vector_foreach_slot (mpp->pg, pgp, j){
705 vector_foreach_slot (pgp->paths, pp, i){
706 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
707 condlog (1, "%s: %s path not up.", mpp->wwid, pp->dev);
711 strncpy(thread[count].param.dev, pp->dev,
713 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
714 rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
715 (void *) (&thread[count].param));
717 condlog (0, "%s: failed to create thread. %d", mpp->wwid, rc);
718 thread[count].param.status = MPATH_PR_THREAD_ERROR;
723 pthread_attr_destroy (&attr);
724 for (i = 0; i < count; i++){
725 if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
726 rc = pthread_join (thread[i].id, NULL);
728 condlog (1, "%s: failed to join thread. %d", mpp->wwid, rc);
733 for (i = 0; i < count; i++){
734 /* check thread status here and return the status */
736 if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
737 status = MPATH_PR_RESERV_CONFLICT;
738 else if (status == MPATH_PR_SUCCESS
739 && thread[i].param.status != MPATH_PR_RESERV_CONFLICT)
740 status = thread[i].param.status;
743 status = mpath_prin_activepath (mpp, MPATH_PRIN_RRES_SA, &resp, noisy);
744 if (status != MPATH_PR_SUCCESS){
745 condlog (0, "%s: pr in read reservation command failed.", mpp->wwid);
746 return MPATH_PR_OTHER;
749 num = resp.prin_descriptor.prin_readresv.additional_length / 8;
751 condlog (2, "%s: Path holding reservation is released.", mpp->wwid);
752 return MPATH_PR_SUCCESS;
754 condlog (2, "%s: Path holding reservation is not avialable.", mpp->wwid);
756 pr_buff = mpath_alloc_prin_response(MPATH_PRIN_RFSTAT_SA);
758 condlog (0, "%s: failed to alloc pr in response buffer.", mpp->wwid);
759 return MPATH_PR_OTHER;
762 status = mpath_prin_activepath (mpp, MPATH_PRIN_RFSTAT_SA, pr_buff, noisy);
764 if (status != MPATH_PR_SUCCESS){
765 condlog (0, "%s: pr in read full status command failed.", mpp->wwid);
769 num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
773 length = sizeof (struct prout_param_descriptor) + (sizeof (struct transportid *));
775 pamp = (struct prout_param_descriptor *)malloc (length);
777 condlog (0, "%s: failed to alloc pr out parameter.", mpp->wwid);
781 memset(pamp, 0, length);
783 pamp->trnptid_list[0] = (struct transportid *) malloc (sizeof (struct transportid));
784 if (!pamp->trnptid_list[0]){
785 condlog (0, "%s: failed to alloc pr out transportid.", mpp->wwid);
789 if (get_be64(mpp->reservation_key)){
790 memcpy (pamp->key, &mpp->reservation_key, 8);
791 condlog (3, "%s: reservation key set.", mpp->wwid);
794 status = mpath_prout_common (mpp, MPATH_PROUT_CLEAR_SA,
795 rq_scope, rq_type, pamp, noisy);
798 condlog(0, "%s: failed to send CLEAR_SA", mpp->wwid);
802 pamp->num_transportid = 1;
803 pptr=pamp->trnptid_list[0];
805 for (i = 0; i < num; i++){
806 if (get_be64(mpp->reservation_key) &&
807 memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
808 &mpp->reservation_key, 8)){
809 /*register with tarnsport id*/
810 memset(pamp, 0, length);
811 pamp->trnptid_list[0] = pptr;
812 memset (pamp->trnptid_list[0], 0, sizeof (struct transportid));
813 memcpy (pamp->sa_key,
814 pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
815 pamp->sa_flags = MPATH_F_SPEC_I_PT_MASK;
816 pamp->num_transportid = 1;
818 memcpy (pamp->trnptid_list[0],
819 &pr_buff->prin_descriptor.prin_readfd.descriptors[i]->trnptid,
820 sizeof (struct transportid));
821 status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
825 memcpy (pamp->key, pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
826 memset (pamp->sa_key, 0, 8);
827 pamp->num_transportid = 0;
828 status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
833 if (get_be64(mpp->reservation_key))
841 memset (pamp, 0, length);
842 memcpy (pamp->sa_key, &mpp->reservation_key, 8);
843 memset (pamp->key, 0, 8);
844 status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);
856 void * mpath_alloc_prin_response(int prin_sa)
862 case MPATH_PRIN_RKEY_SA:
863 size = sizeof(struct prin_readdescr);
865 case MPATH_PRIN_RRES_SA:
866 size = sizeof(struct prin_resvdescr);
868 case MPATH_PRIN_RCAP_SA:
869 size=sizeof(struct prin_capdescr);
871 case MPATH_PRIN_RFSTAT_SA:
872 size = sizeof(struct print_fulldescr_list) +
873 sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
878 ptr = calloc(size, 1);
883 int update_map_pr(struct multipath *mpp)
886 struct prin_resp *resp;
889 if (!get_be64(mpp->reservation_key))
891 /* Nothing to do. Assuming pr mgmt feature is disabled*/
892 condlog(3, "%s: reservation_key not set in multipath.conf", mpp->alias);
893 return MPATH_PR_SUCCESS;
896 resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
899 condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
900 return MPATH_PR_OTHER;
902 ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
904 if (ret != MPATH_PR_SUCCESS )
906 condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
911 if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
913 condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
915 return MPATH_PR_SUCCESS;
918 condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias,
919 get_be64(mpp->reservation_key));
922 for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
924 condlog(2, "%s: PR IN READKEYS[%d] reservation key:", mpp->alias, i);
925 dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
927 if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
929 condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
937 condlog(2, "%s: prflag flag set.", mpp->alias );
941 return MPATH_PR_SUCCESS;