There is a race condition when changing reservation keys where a failed path could come back online after libmpathpersist checks the paths, but before it updates the reservation key. In this case, the path would come up and get reregistered with the old key by multipathd, and libmpathpersist would not update its key, because the path was down when it checked.
To fix this, check the paths after updating the key, so any path that comes up after getting checked will use the updated key. Signed-off-by: Benjamin Marzinski <bmarz...@redhat.com> --- libmpathpersist/mpath_persist_int.c | 69 ++++++++++++----------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c index ca3dab5c..06747391 100644 --- a/libmpathpersist/mpath_persist_int.c +++ b/libmpathpersist/mpath_persist_int.c @@ -111,39 +111,18 @@ void *mpath_alloc_prin_response(int prin_sa) return ptr; } -static int get_mpvec(vector curmp, vector pathvec, char *refwwid) +static int get_path_info(struct multipath *mpp, vector pathvec) { - int i; - struct multipath *mpp; - - vector_foreach_slot (curmp, mpp, i){ - /* - * discard out of scope maps - */ - if (!mpp->alias) { - condlog(0, "%s: map with empty alias!", __func__); - continue; - } - - if (mpp->pg != NULL) - /* Already seen this one */ - continue; - - if (refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE - 1)) - continue; - - if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK || - update_mpp_paths(mpp, pathvec)) { - condlog(1, "error parsing map %s", mpp->wwid); - remove_map(mpp, pathvec, curmp); - i--; - } else - extract_hwe_from_path(mpp); + if (update_multipath_table(mpp, pathvec, DI_CHECKER) != DMP_OK || + update_mpp_paths(mpp, pathvec)) { + condlog(0, "error parsing map %s", mpp->wwid); + return MPATH_PR_DMMP_ERROR; } + extract_hwe_from_path(mpp); return MPATH_PR_SUCCESS ; } -static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath **pmpp) +static int mpath_get_map(vector curmp, int fd, struct multipath **pmpp) { int rc; struct stat info; @@ -175,12 +154,6 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath condlog(4, "alias = %s", alias); - /* get info of all paths from the dm device */ - if (get_mpvec(curmp, pathvec, alias)) { - condlog(0, "%s: failed to get device info.", alias); - return MPATH_PR_DMMP_ERROR; - } - mpp = find_mp_by_alias(curmp, alias); if (!mpp) { @@ -201,7 +174,11 @@ int do_mpath_persistent_reserve_in(vector curmp, vector pathvec, struct multipath *mpp; int ret; - ret = mpath_get_map(curmp, pathvec, fd, &mpp); + ret = mpath_get_map(curmp, fd, &mpp); + if (ret != MPATH_PR_SUCCESS) + return ret; + + ret = get_path_info(mpp, pathvec); if (ret != MPATH_PR_SUCCESS) return ret; @@ -734,20 +711,15 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, bool unregistering, preempting_reservation = false; bool updated_prkey = false; - ret = mpath_get_map(curmp, pathvec, fd, &mpp); + ret = mpath_get_map(curmp, fd, &mpp); if (ret != MPATH_PR_SUCCESS) return ret; conf = get_multipath_config(); mpp->mpe = find_mpe(conf->mptable, mpp->wwid); select_reservation_key(conf, mpp); - select_all_tg_pt(conf, mpp); - select_skip_kpartx(conf, mpp); put_multipath_config(conf); - if (rq_servact == MPATH_PROUT_REG_IGN_SA) - set_ignored_key(mpp, paramp->key); - unregistering = (memcmp(&zerokey, paramp->sa_key, 8) == 0); if (mpp->prkey_source == PRKEY_SOURCE_FILE && (rq_servact == MPATH_PROUT_REG_IGN_SA || @@ -798,6 +770,21 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, } } + ret = get_path_info(mpp, pathvec); + if (ret != MPATH_PR_SUCCESS) { + if (updated_prkey) + update_prkey_flags(mpp->alias, get_be64(oldkey), + mpp->sa_flags); + return ret; + } + + conf = get_multipath_config(); + select_all_tg_pt(conf, mpp); + select_skip_kpartx(conf, mpp); + put_multipath_config(conf); + + if (rq_servact == MPATH_PROUT_REG_IGN_SA) + set_ignored_key(mpp, paramp->key); switch(rq_servact) { -- 2.48.1