1 #include <libdevmapper.h>
9 #include "structs_vec.h"
14 #include "devmapper.h"
17 #include "switchgroup.h"
18 #include "discovery.h"
19 #include "configure.h"
24 #include "unaligned.h"
26 #include "mpath_persist.h"
28 #include "mpath_pr_ioctl.h"
36 #define __STDC_FORMAT_MACROS 1
38 extern struct udev *udev;
40 static void adapt_config(struct config *conf)
43 set_max_fds(conf->max_fds);
46 int libmpathpersist_init(void)
51 if (libmultipath_init()) {
52 condlog(0, "Failed to initialize libmultipath.");
55 if (init_config(DEFAULT_CONFIGFILE)) {
56 condlog(0, "Failed to initialize multipath config.");
59 conf = libmp_get_multipath_config();
61 libmp_put_multipath_config(conf);
70 conf = load_config(DEFAULT_CONFIGFILE);
72 condlog(0, "Failed to initialize multipath config.");
79 static void libmpathpersist_cleanup(void)
86 mpath_lib_exit (struct config *conf)
89 libmpathpersist_cleanup();
93 int libmpathpersist_exit(void)
96 libmpathpersist_cleanup();
101 mpath_prin_activepath (struct multipath *mpp, int rq_servact,
102 struct prin_resp * resp, int noisy)
104 int i,j, ret = MPATH_PR_DMMP_ERROR;
105 struct pathgroup *pgp = NULL;
106 struct path *pp = NULL;
108 vector_foreach_slot (mpp->pg, pgp, j){
109 vector_foreach_slot (pgp->paths, pp, i){
110 if (!((pp->state == PATH_UP) ||
111 (pp->state == PATH_GHOST))){
112 condlog(2, "%s: %s not available. Skip.",
114 condlog(3, "%s: status = %d.",
115 mpp->wwid, pp->state);
119 condlog(3, "%s: sending pr in command to %s ",
121 ret = mpath_send_prin_activepath(pp->dev, rq_servact,
125 case MPATH_PR_SUCCESS:
126 case MPATH_PR_SENSE_INVALID_OP:
137 static vector pathvec;
139 static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec)
141 free_multipathvec(curmp, KEEP_PATHS);
142 free_pathvec(pathvec, FREE_PATHS);
145 void mpath_persistent_reserve_free_vecs(void)
147 __mpath_persistent_reserve_free_vecs(curmp, pathvec);
148 curmp = pathvec = NULL;
151 static int __mpath_persistent_reserve_init_vecs(vector *curmp_p,
152 vector *pathvec_p, int verbose)
154 libmp_verbosity = verbose;
157 return MPATH_PR_SUCCESS;
159 * allocate core vectors to store paths and multipaths
161 *curmp_p = vector_alloc ();
162 *pathvec_p = vector_alloc ();
164 if (!*curmp_p || !*pathvec_p){
165 condlog (0, "vector allocation failed.");
169 if (dm_get_maps(*curmp_p))
172 return MPATH_PR_SUCCESS;
175 __mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p);
176 *curmp_p = *pathvec_p = NULL;
177 return MPATH_PR_DMMP_ERROR;
180 int mpath_persistent_reserve_init_vecs(int verbose)
182 return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
185 static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
186 struct multipath **pmpp)
188 int ret = MPATH_PR_DMMP_ERROR;
192 struct multipath *mpp;
194 if (fstat(fd, &info) != 0){
195 condlog(0, "stat error fd=%d", fd);
196 return MPATH_PR_FILE_ERROR;
198 if(!S_ISBLK(info.st_mode)){
199 condlog(3, "Failed to get major:minor. fd=%d", fd);
200 return MPATH_PR_FILE_ERROR;
203 major = major(info.st_rdev);
204 minor = minor(info.st_rdev);
205 condlog(4, "Device %d:%d", major, minor);
207 /* get alias from major:minor*/
208 alias = dm_mapname(major, minor);
210 condlog(0, "%d:%d failed to get device alias.", major, minor);
211 return MPATH_PR_DMMP_ERROR;
214 condlog(3, "alias = %s", alias);
216 if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
217 condlog(3, "%s: not a multipath device.", alias);
221 /* get info of all paths from the dm device */
222 if (get_mpvec(curmp, pathvec, alias)){
223 condlog(0, "%s: failed to get device info.", alias);
227 mpp = find_mp_by_alias(curmp, alias);
230 condlog(0, "%s: devmap not registered.", alias);
234 ret = MPATH_PR_SUCCESS;
246 static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
247 int fd, int rq_servact, struct prin_resp *resp, int noisy)
249 struct multipath *mpp;
252 ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
253 if (ret != MPATH_PR_SUCCESS)
256 ret = mpath_prin_activepath(mpp, rq_servact, resp, noisy);
262 int __mpath_persistent_reserve_in (int fd, int rq_servact,
263 struct prin_resp *resp, int noisy)
265 return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
269 static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
270 int rq_servact, int rq_scope, unsigned int rq_type,
271 struct prout_param_descriptor *paramp, int noisy)
273 struct multipath *mpp;
279 ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
280 if (ret != MPATH_PR_SUCCESS)
283 conf = get_multipath_config();
284 select_reservation_key(conf, mpp);
285 select_all_tg_pt(conf, mpp);
286 put_multipath_config(conf);
288 memcpy(&prkey, paramp->sa_key, 8);
289 if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
290 (rq_servact == MPATH_PROUT_REG_IGN_SA ||
291 (rq_servact == MPATH_PROUT_REG_SA &&
292 (!get_be64(mpp->reservation_key) ||
293 memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
294 memcpy(&mpp->reservation_key, paramp->sa_key, 8);
295 if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
297 condlog(0, "%s: failed to set prkey for multipathd.",
299 ret = MPATH_PR_DMMP_ERROR;
304 if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
305 memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
306 (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
307 condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
308 ret = MPATH_PR_SYNTAX_ERROR;
314 case MPATH_PROUT_REG_SA:
315 case MPATH_PROUT_REG_IGN_SA:
316 ret= mpath_prout_reg(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
318 case MPATH_PROUT_RES_SA :
319 case MPATH_PROUT_PREE_SA :
320 case MPATH_PROUT_PREE_AB_SA :
321 case MPATH_PROUT_CLEAR_SA:
322 ret = mpath_prout_common(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
324 case MPATH_PROUT_REL_SA:
325 ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
328 ret = MPATH_PR_OTHER;
332 if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
333 (rq_servact == MPATH_PROUT_REG_IGN_SA)))
336 update_prflag(alias, 0);
337 update_prkey(alias, 0);
339 update_prflag(alias, 1);
340 } else if ((ret == MPATH_PR_SUCCESS) && (rq_servact == MPATH_PROUT_CLEAR_SA)) {
341 update_prflag(alias, 0);
342 update_prkey(alias, 0);
350 int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
351 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
353 return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
354 rq_scope, rq_type, paramp,
358 int mpath_persistent_reserve_in (int fd, int rq_servact,
359 struct prin_resp *resp, int noisy, int verbose)
361 vector curmp = NULL, pathvec;
362 int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
365 if (ret != MPATH_PR_SUCCESS)
367 ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
369 __mpath_persistent_reserve_free_vecs(curmp, pathvec);
373 int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
374 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
376 vector curmp = NULL, pathvec;
377 int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
380 if (ret != MPATH_PR_SUCCESS)
382 ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
383 rq_scope, rq_type, paramp, noisy);
384 __mpath_persistent_reserve_free_vecs(curmp, pathvec);
389 get_mpvec (vector curmp, vector pathvec, char * refwwid)
392 struct multipath *mpp;
394 vector_foreach_slot (curmp, mpp, i){
396 * discard out of scope maps
399 condlog(0, "%s: map with empty alias!", __func__);
404 /* Already seen this one */
407 if (refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE - 1))
410 if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK ||
411 update_mpp_paths(mpp, pathvec)) {
412 condlog(1, "error parsing map %s", mpp->wwid);
413 remove_map(mpp, pathvec, curmp);
416 extract_hwe_from_path(mpp);
418 return MPATH_PR_SUCCESS ;
421 int mpath_send_prin_activepath (char * dev, int rq_servact,
422 struct prin_resp * resp, int noisy)
427 rc = prin_do_scsi_ioctl(dev, rq_servact, resp, noisy);
432 int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
433 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
437 struct pathgroup *pgp = NULL;
438 struct path *pp = NULL;
440 int active_pathcount=0;
443 int status = MPATH_PR_SUCCESS;
448 return MPATH_PR_DMMP_ERROR;
450 all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON ||
451 paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK);
452 active_pathcount = count_active_paths(mpp);
454 if (active_pathcount == 0) {
455 condlog (0, "%s: no path available", mpp->wwid);
456 return MPATH_PR_DMMP_ERROR;
459 struct threadinfo thread[active_pathcount];
460 int hosts[active_pathcount];
462 memset(thread, 0, sizeof(thread));
464 /* init thread parameter */
465 for (i =0; i< active_pathcount; i++){
467 thread[i].param.rq_servact = rq_servact;
468 thread[i].param.rq_scope = rq_scope;
469 thread[i].param.rq_type = rq_type;
470 thread[i].param.paramp = paramp;
471 thread[i].param.noisy = noisy;
472 thread[i].param.status = MPATH_PR_SKIP;
474 condlog (3, "THREAD ID [%d] INFO]", i);
475 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
476 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
477 condlog (3, "rq_type=%d ", thread[i].param.rq_type);
478 condlog (3, "rkey=");
479 condlog (3, "paramp->sa_flags =%02x ",
480 thread[i].param.paramp->sa_flags);
481 condlog (3, "noisy=%d ", thread[i].param.noisy);
482 condlog (3, "status=%d ", thread[i].param.status);
486 pthread_attr_init(&attr);
487 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
489 vector_foreach_slot (mpp->pg, pgp, j){
490 vector_foreach_slot (pgp->paths, pp, i){
491 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
492 condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
495 if (all_tg_pt && pp->sg_id.host_no != -1) {
496 for (k = 0; k < count; k++) {
497 if (pp->sg_id.host_no == hosts[k]) {
498 condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no);
505 strlcpy(thread[count].param.dev, pp->dev,
508 if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
510 * Clearing SPEC_I_PT as transportids are already registered by now.
512 thread[count].param.paramp->sa_flags &= (~MPATH_F_SPEC_I_PT_MASK);
515 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
517 rc = pthread_create(&thread[count].id, &attr, mpath_prout_pthread_fn, (void *)(&thread[count].param));
519 condlog (0, "%s: failed to create thread %d", mpp->wwid, rc);
520 thread[count].param.status = MPATH_PR_THREAD_ERROR;
523 hosts[count] = pp->sg_id.host_no;
527 for( i=0; i < count ; i++){
528 if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
529 rc = pthread_join(thread[i].id, NULL);
531 condlog (0, "%s: Thread[%d] failed to join thread %d", mpp->wwid, i, rc);
534 if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){
536 sa_key = get_unaligned_be64(¶mp->sa_key[0]);
537 status = MPATH_PR_RESERV_CONFLICT ;
539 if (!rollback && (status == MPATH_PR_SUCCESS)){
540 status = thread[i].param.status;
543 if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){
544 condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid);
545 memcpy(¶mp->key, ¶mp->sa_key, 8);
546 memset(¶mp->sa_key, 0, 8);
547 for( i=0 ; i < count ; i++){
548 if(thread[i].param.status == MPATH_PR_SUCCESS) {
549 rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
550 (void *)(&thread[i].param));
552 condlog (0, "%s: failed to create thread for rollback. %d", mpp->wwid, rc);
553 thread[i].param.status = MPATH_PR_THREAD_ERROR;
556 thread[i].param.status = MPATH_PR_SKIP;
558 for(i=0; i < count ; i++){
559 if (thread[i].param.status != MPATH_PR_SKIP &&
560 thread[i].param.status != MPATH_PR_THREAD_ERROR) {
561 rc = pthread_join(thread[i].id, NULL);
563 condlog (3, "%s: failed to join thread while rolling back %d",
570 pthread_attr_destroy(&attr);
574 void * mpath_prout_pthread_fn(void *p)
577 struct prout_param * param = (struct prout_param *)p;
579 ret = prout_do_scsi_ioctl( param->dev,param->rq_servact, param->rq_scope,
580 param->rq_type, param->paramp, param->noisy);
585 int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
586 unsigned int rq_type, struct prout_param_descriptor* paramp, int noisy)
589 struct pathgroup *pgp = NULL;
590 struct path *pp = NULL;
592 vector_foreach_slot (mpp->pg, pgp, j){
593 vector_foreach_slot (pgp->paths, pp, i){
594 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
595 condlog (1, "%s: %s path not up. Skip",
600 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
601 ret = send_prout_activepath(pp->dev, rq_servact,
607 condlog (0, "%s: no path available", mpp->wwid);
608 return MPATH_PR_DMMP_ERROR;
611 int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
612 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
614 struct prout_param param;
615 param.rq_servact = rq_servact;
616 param.rq_scope = rq_scope;
617 param.rq_type = rq_type;
618 param.paramp = paramp;
626 memset(&thread, 0, sizeof(thread));
627 strlcpy(param.dev, dev, FILE_NAME_SIZE);
628 /* Initialize and set thread joinable attribute */
629 pthread_attr_init(&attr);
630 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
632 rc = pthread_create(&thread, &attr, mpath_prout_pthread_fn, (void *)(¶m));
634 condlog (3, "%s: failed to create thread %d", dev, rc);
635 return MPATH_PR_THREAD_ERROR;
637 /* Free attribute and wait for the other threads */
638 pthread_attr_destroy(&attr);
639 rc = pthread_join(thread, NULL);
641 return (param.status);
644 int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
645 unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy)
649 struct pathgroup *pgp = NULL;
650 struct path *pp = NULL;
651 int active_pathcount = 0;
655 int status = MPATH_PR_SUCCESS;
656 struct prin_resp resp;
657 struct prout_param_descriptor *pamp;
658 struct prin_resp *pr_buff;
660 struct transportid *pptr;
663 return MPATH_PR_DMMP_ERROR;
665 active_pathcount = count_active_paths(mpp);
667 if (active_pathcount == 0) {
668 condlog (0, "%s: no path available", mpp->wwid);
669 return MPATH_PR_DMMP_ERROR;
672 struct threadinfo thread[active_pathcount];
673 memset(thread, 0, sizeof(thread));
674 for (i = 0; i < active_pathcount; i++){
675 thread[i].param.rq_servact = rq_servact;
676 thread[i].param.rq_scope = rq_scope;
677 thread[i].param.rq_type = rq_type;
678 thread[i].param.paramp = paramp;
679 thread[i].param.noisy = noisy;
680 thread[i].param.status = MPATH_PR_SKIP;
682 condlog (3, " path count = %d", i);
683 condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
684 condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
685 condlog (3, "rq_type=%d ", thread[i].param.rq_type);
686 condlog (3, "noisy=%d ", thread[i].param.noisy);
687 condlog (3, "status=%d ", thread[i].param.status);
690 pthread_attr_init (&attr);
691 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
693 vector_foreach_slot (mpp->pg, pgp, j){
694 vector_foreach_slot (pgp->paths, pp, i){
695 if (!((pp->state == PATH_UP) || (pp->state == PATH_GHOST))){
696 condlog (1, "%s: %s path not up.", mpp->wwid, pp->dev);
700 strlcpy(thread[count].param.dev, pp->dev,
702 condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
703 rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
704 (void *) (&thread[count].param));
706 condlog (0, "%s: failed to create thread. %d", mpp->wwid, rc);
707 thread[count].param.status = MPATH_PR_THREAD_ERROR;
712 pthread_attr_destroy (&attr);
713 for (i = 0; i < count; i++){
714 if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
715 rc = pthread_join (thread[i].id, NULL);
717 condlog (1, "%s: failed to join thread. %d", mpp->wwid, rc);
722 for (i = 0; i < count; i++){
723 /* check thread status here and return the status */
725 if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)
726 status = MPATH_PR_RESERV_CONFLICT;
727 else if (status == MPATH_PR_SUCCESS
728 && thread[i].param.status != MPATH_PR_RESERV_CONFLICT)
729 status = thread[i].param.status;
732 status = mpath_prin_activepath (mpp, MPATH_PRIN_RRES_SA, &resp, noisy);
733 if (status != MPATH_PR_SUCCESS){
734 condlog (0, "%s: pr in read reservation command failed.", mpp->wwid);
735 return MPATH_PR_OTHER;
738 num = resp.prin_descriptor.prin_readresv.additional_length / 8;
740 condlog (2, "%s: Path holding reservation is released.", mpp->wwid);
741 return MPATH_PR_SUCCESS;
743 condlog (2, "%s: Path holding reservation is not avialable.", mpp->wwid);
745 pr_buff = mpath_alloc_prin_response(MPATH_PRIN_RFSTAT_SA);
747 condlog (0, "%s: failed to alloc pr in response buffer.", mpp->wwid);
748 return MPATH_PR_OTHER;
751 status = mpath_prin_activepath (mpp, MPATH_PRIN_RFSTAT_SA, pr_buff, noisy);
753 if (status != MPATH_PR_SUCCESS){
754 condlog (0, "%s: pr in read full status command failed.", mpp->wwid);
758 num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
762 length = sizeof (struct prout_param_descriptor) + (sizeof (struct transportid *));
764 pamp = (struct prout_param_descriptor *)malloc (length);
766 condlog (0, "%s: failed to alloc pr out parameter.", mpp->wwid);
770 memset(pamp, 0, length);
772 pamp->trnptid_list[0] = (struct transportid *) malloc (sizeof (struct transportid));
773 if (!pamp->trnptid_list[0]){
774 condlog (0, "%s: failed to alloc pr out transportid.", mpp->wwid);
778 if (get_be64(mpp->reservation_key)){
779 memcpy (pamp->key, &mpp->reservation_key, 8);
780 condlog (3, "%s: reservation key set.", mpp->wwid);
783 status = mpath_prout_common (mpp, MPATH_PROUT_CLEAR_SA,
784 rq_scope, rq_type, pamp, noisy);
787 condlog(0, "%s: failed to send CLEAR_SA", mpp->wwid);
791 pamp->num_transportid = 1;
792 pptr=pamp->trnptid_list[0];
794 for (i = 0; i < num; i++){
795 if (get_be64(mpp->reservation_key) &&
796 memcmp(pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key,
797 &mpp->reservation_key, 8)){
798 /*register with tarnsport id*/
799 memset(pamp, 0, length);
800 pamp->trnptid_list[0] = pptr;
801 memset (pamp->trnptid_list[0], 0, sizeof (struct transportid));
802 memcpy (pamp->sa_key,
803 pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
804 pamp->sa_flags = MPATH_F_SPEC_I_PT_MASK;
805 pamp->num_transportid = 1;
807 memcpy (pamp->trnptid_list[0],
808 &pr_buff->prin_descriptor.prin_readfd.descriptors[i]->trnptid,
809 sizeof (struct transportid));
810 status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
814 memcpy (pamp->key, pr_buff->prin_descriptor.prin_readfd.descriptors[i]->key, 8);
815 memset (pamp->sa_key, 0, 8);
816 pamp->num_transportid = 0;
817 status = mpath_prout_common (mpp, MPATH_PROUT_REG_SA, 0, rq_type,
822 if (get_be64(mpp->reservation_key))
830 memset (pamp, 0, length);
831 memcpy (pamp->sa_key, &mpp->reservation_key, 8);
832 memset (pamp->key, 0, 8);
833 status = mpath_prout_reg(mpp, MPATH_PROUT_REG_SA, rq_scope, rq_type, pamp, noisy);
845 void * mpath_alloc_prin_response(int prin_sa)
851 case MPATH_PRIN_RKEY_SA:
852 size = sizeof(struct prin_readdescr);
854 case MPATH_PRIN_RRES_SA:
855 size = sizeof(struct prin_resvdescr);
857 case MPATH_PRIN_RCAP_SA:
858 size=sizeof(struct prin_capdescr);
860 case MPATH_PRIN_RFSTAT_SA:
861 size = sizeof(struct print_fulldescr_list) +
862 sizeof(struct prin_fulldescr *)*MPATH_MX_TIDS;
867 ptr = calloc(size, 1);
872 int update_map_pr(struct multipath *mpp)
875 struct prin_resp *resp;
879 if (!get_be64(mpp->reservation_key))
881 /* Nothing to do. Assuming pr mgmt feature is disabled*/
882 condlog(4, "%s: reservation_key not set in multipath.conf",
884 return MPATH_PR_SUCCESS;
887 resp = mpath_alloc_prin_response(MPATH_PRIN_RKEY_SA);
890 condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
891 return MPATH_PR_OTHER;
893 ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
895 if (ret != MPATH_PR_SUCCESS )
897 condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
902 if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
904 condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
906 return MPATH_PR_SUCCESS;
909 condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias,
910 get_be64(mpp->reservation_key));
913 for (i = 0; i < resp->prin_descriptor.prin_readkeys.additional_length/8; i++ )
915 condlog(2, "%s: PR IN READKEYS[%d] reservation key:", mpp->alias, i);
916 dumpHex((char *)&resp->prin_descriptor.prin_readkeys.key_list[i*8], 8 , 1);
918 if (!memcmp(&mpp->reservation_key, &resp->prin_descriptor.prin_readkeys.key_list[i*8], 8))
920 condlog(2, "%s: reservation key found in pr in readkeys response", mpp->alias);
928 condlog(2, "%s: prflag flag set.", mpp->alias );
932 return MPATH_PR_SUCCESS;