@@ -200,7 +200,7 @@ static void *mpath_prout_pthread_fn(void *p)
200200static int
201201mpath_prout_common (struct multipath * mpp , int rq_servact , int rq_scope ,
202202 unsigned int rq_type , struct prout_param_descriptor * paramp ,
203- int noisy , struct path * * pptr )
203+ int noisy , struct path * * pptr , bool * failed_paths )
204204{
205205 int i , j , ret ;
206206 struct pathgroup * pgp = NULL ;
@@ -213,6 +213,8 @@ mpath_prout_common(struct multipath *mpp, int rq_servact, int rq_scope,
213213 if (!((pp -> state == PATH_UP ) || (pp -> state == PATH_GHOST ))) {
214214 condlog (1 , "%s: %s path not up. Skip" ,
215215 mpp -> wwid , pp -> dev );
216+ if (failed_paths )
217+ * failed_paths = true;
216218 continue ;
217219 }
218220
@@ -247,6 +249,8 @@ mpath_prout_common(struct multipath *mpp, int rq_servact, int rq_scope,
247249 }
248250 if (ret != MPATH_PR_RETRYABLE_ERROR )
249251 return ret ;
252+ if (failed_paths )
253+ * failed_paths = true;
250254 }
251255 }
252256 if (found )
@@ -333,7 +337,7 @@ void preempt_missing_path(struct multipath *mpp, uint8_t *key, uint8_t *sa_key,
333337 memcpy (paramp .key , sa_key , 8 );
334338 memcpy (paramp .sa_key , key , 8 );
335339 status = mpath_prout_common (mpp , MPATH_PROUT_PREE_SA , rq_scope ,
336- rq_type , & paramp , noisy , NULL );
340+ rq_type , & paramp , noisy , NULL , NULL );
337341 if (status != MPATH_PR_SUCCESS )
338342 condlog (0 , "%s: register: pr preempt command failed." , mpp -> wwid );
339343}
@@ -586,7 +590,7 @@ static int do_preempt_self(struct multipath *mpp, struct be64 sa_key,
586590 memcpy (paramp .key , & mpp -> reservation_key , 8 );
587591 memcpy (paramp .sa_key , & sa_key , 8 );
588592 status = mpath_prout_common (mpp , rq_servact , rq_scope , rq_type ,
589- & paramp , noisy , & pp );
593+ & paramp , noisy , & pp , NULL );
590594 if (status != MPATH_PR_SUCCESS ) {
591595 condlog (0 , "%s: self preempt command failed." , mpp -> wwid );
592596 goto fail_resume ;
@@ -769,20 +773,25 @@ static int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
769773 return preempt_self (mpp , MPATH_PROUT_PREE_SA , rq_scope , rq_type , noisy , true);
770774}
771775
772- static int reservation_key_matches (struct multipath * mpp , uint8_t * key , int noisy )
776+ static int
777+ reservation_key_matches (struct multipath * mpp , uint8_t * key , unsigned int * type )
773778{
774779 struct prin_resp resp = {{{.prgeneration = 0 }}};
775780 int status ;
776781
777- status = mpath_prin_activepath (mpp , MPATH_PRIN_RRES_SA , & resp , noisy );
782+ status = mpath_prin_activepath (mpp , MPATH_PRIN_RRES_SA , & resp , 0 );
778783 if (status != MPATH_PR_SUCCESS ) {
779784 condlog (0 , "%s: pr in read reservation command failed." , mpp -> wwid );
780785 return YNU_UNDEF ;
781786 }
782787 if (!resp .prin_descriptor .prin_readresv .additional_length )
783788 return YNU_NO ;
784- if (memcmp (key , resp .prin_descriptor .prin_readresv .key , 8 ) == 0 )
789+ if (memcmp (key , resp .prin_descriptor .prin_readresv .key , 8 ) == 0 ) {
790+ if (type )
791+ * type = resp .prin_descriptor .prin_readresv .scope_type &
792+ MPATH_PR_TYPE_MASK ;
785793 return YNU_YES ;
794+ }
786795 return YNU_NO ;
787796}
788797
@@ -798,11 +807,20 @@ static void set_ignored_key(struct multipath *mpp, uint8_t *curr_key, uint8_t *k
798807 return ;
799808 if (get_prhold (mpp -> alias ) == PR_UNSET )
800809 return ;
801- if (reservation_key_matches (mpp , curr_key , 0 ) == YNU_NO )
810+ if (reservation_key_matches (mpp , curr_key , NULL ) == YNU_NO )
802811 return ;
803812 memcpy (key , curr_key , 8 );
804813}
805814
815+ static bool check_holding_reservation (struct multipath * mpp , unsigned int * type )
816+ {
817+ if (get_be64 (mpp -> reservation_key ) && get_prhold (mpp -> alias ) == PR_SET &&
818+ reservation_key_matches (mpp , (uint8_t * )& mpp -> reservation_key , type ) ==
819+ YNU_YES )
820+ return true;
821+ return false;
822+ }
823+
806824int do_mpath_persistent_reserve_out (vector curmp , vector pathvec , int fd ,
807825 int rq_servact , int rq_scope , unsigned int rq_type ,
808826 struct prout_param_descriptor * paramp , int noisy )
@@ -814,6 +832,7 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
814832 struct config * conf ;
815833 bool unregistering , preempting_reservation = false;
816834 bool updated_prkey = false;
835+ bool failed_paths = false;
817836
818837 ret = mpath_get_map (curmp , fd , & mpp );
819838 if (ret != MPATH_PR_SUCCESS )
@@ -905,7 +924,7 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
905924 break ;
906925 case MPATH_PROUT_PREE_SA :
907926 case MPATH_PROUT_PREE_AB_SA :
908- if (reservation_key_matches (mpp , paramp -> sa_key , noisy ) == YNU_YES ) {
927+ if (reservation_key_matches (mpp , paramp -> sa_key , NULL ) == YNU_YES ) {
909928 preempting_reservation = true;
910929 if (memcmp (paramp -> sa_key , & zerokey , 8 ) == 0 ) {
911930 /* all registrants case */
@@ -922,10 +941,17 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
922941 }
923942 /* fallthrough */
924943 case MPATH_PROUT_RES_SA :
925- case MPATH_PROUT_CLEAR_SA :
944+ case MPATH_PROUT_CLEAR_SA : {
945+ unsigned int res_type ;
926946 ret = mpath_prout_common (mpp , rq_servact , rq_scope , rq_type ,
927- paramp , noisy , NULL );
947+ paramp , noisy , NULL , & failed_paths );
948+ if (rq_servact == MPATH_PROUT_RES_SA && ret != MPATH_PR_SUCCESS &&
949+ failed_paths && check_holding_reservation (mpp , & res_type ) &&
950+ res_type == rq_type )
951+ /* The reserve failed, but multipathd says we hold it */
952+ ret = MPATH_PR_SUCCESS ;
928953 break ;
954+ }
929955 case MPATH_PROUT_REL_SA :
930956 ret = mpath_prout_rel (mpp , rq_servact , rq_scope , rq_type , paramp , noisy );
931957 break ;
0 commit comments