Skip to content

Commit 60b1da9

Browse files
bmarzinsmwilck
authored andcommitted
libmpathpersist: Handle RESERVE with reservation held by failed path
Issuing a RESERVE on a device that already holds the reservation should succeed, as long as the type is the same. But if the path that holds the reservation is unavailable, mpathpersist fails, since it gets a reservation conflict on all available paths. To deal with this, if the multipath device has failed paths, and the key holding the reservation matches the multipath device's key, and multipathd says that it is holding the reservation, assume the reservation is held by a failed path and claim the RESERVE succeeded, even though none of the actual scsi commands did Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Reviewed-by: Martin Wilck <mwilck@suse.com>
1 parent dedce0c commit 60b1da9

1 file changed

Lines changed: 36 additions & 10 deletions

File tree

libmpathpersist/mpath_persist_int.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static void *mpath_prout_pthread_fn(void *p)
200200
static int
201201
mpath_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+
806824
int 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

Comments
 (0)