When a multipath device is first created, if it has a reservation key configured, update_map_pr() will check for a matching key on the active paths. If there were no active paths to check with, multipathd was leaving mpp->prflag in PRFLAG_UNSET, as if there were no matching keys. It's possible that when update_map_pr() is called, all the paths will be in the PATH_PENDING state because the checkers haven't completed yet. In this case, multipathd was treating the device as having no registered keys without ever checking. To solve this, multipath devices now start with prflag = PRFLAG_UNKNOWN. It will remain in this state until multipathd actually tries to get the registered keys down a path. If the map is in this state, it will check newly active paths, and if it finds a matching key, it will register the key down all active paths. Signed-off-by: Benjamin Marzinski <bmarzins@xxxxxxxxxx> --- libmpathpersist/mpath_persist_int.c | 8 ++++++++ libmultipath/structs.h | 1 + multipathd/cli_handlers.c | 1 + multipathd/main.c | 19 ++++++++++++++----- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c index a84d9474..8b52b746 100644 --- a/libmpathpersist/mpath_persist_int.c +++ b/libmpathpersist/mpath_persist_int.c @@ -738,6 +738,7 @@ int update_map_pr(struct multipath *mpp) if (!get_be64(mpp->reservation_key)) { /* Nothing to do. Assuming pr mgmt feature is disabled*/ + mpp->prflag = PRFLAG_UNSET; condlog(4, "%s: reservation_key not set in multipath.conf", mpp->alias); return MPATH_PR_SUCCESS; @@ -749,6 +750,13 @@ int update_map_pr(struct multipath *mpp) condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias); return MPATH_PR_OTHER; } + if (count_active_paths(mpp) == 0) + { + condlog(0,"%s: No available paths to check pr status", + mpp->alias); + return MPATH_PR_OTHER; + } + mpp->prflag = PRFLAG_UNSET; ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy); if (ret != MPATH_PR_SUCCESS ) diff --git a/libmultipath/structs.h b/libmultipath/structs.h index f2265300..e2294323 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -377,6 +377,7 @@ typedef int (pgpolicyfn) (struct multipath *, vector); enum prflag_value { + PRFLAG_UNKNOWN, PRFLAG_UNSET, PRFLAG_SET, }; diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c index 7ee2729f..ec5db1b8 100644 --- a/multipathd/cli_handlers.c +++ b/multipathd/cli_handlers.c @@ -1278,6 +1278,7 @@ static int cli_getprstatus (void * v, struct strbuf *reply, void * data) { static const char * const prflag_str[] = { + [PRFLAG_UNKNOWN] = "unknown\n", [PRFLAG_UNSET] = "unset\n", [PRFLAG_SET] = "set\n", }; diff --git a/multipathd/main.c b/multipathd/main.c index 722235c7..bdeffe76 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -647,7 +647,7 @@ fail: sync_map_state(mpp); - if (mpp->prflag == PRFLAG_UNSET) + if (mpp->prflag != PRFLAG_SET) update_map_pr(mpp); if (mpp->prflag == PRFLAG_SET) pr_register_active_paths(mpp); @@ -1330,7 +1330,7 @@ rescan: if (retries >= 0) { if (start_waiter) update_map_pr(mpp); - if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET) + if (mpp->prflag == PRFLAG_SET && prflag != PRFLAG_SET) pr_register_active_paths(mpp); condlog(2, "%s [%s]: path added to devmap %s", pp->dev, pp->dev_t, mpp->alias); @@ -2492,13 +2492,17 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks) } if (newstate == PATH_UP || newstate == PATH_GHOST) { - if (pp->mpp->prflag == PRFLAG_SET) { + if (pp->mpp->prflag != PRFLAG_UNSET) { + int prflag = pp->mpp->prflag; /* * Check Persistent Reservation. */ condlog(2, "%s: checking persistent " "reservation registration", pp->dev); mpath_pr_event_handle(pp); + if (pp->mpp->prflag == PRFLAG_SET && + prflag != PRFLAG_SET) + pr_register_active_paths(pp->mpp); } } @@ -3788,6 +3792,7 @@ void * mpath_pr_event_handler_fn (void * pathp ) goto out; } + mpp->prflag = PRFLAG_UNSET; ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, resp, 0); if (ret != MPATH_PR_SUCCESS ) { @@ -3858,12 +3863,12 @@ int mpath_pr_event_handle(struct path *pp) struct multipath * mpp; if (pp->bus != SYSFS_BUS_SCSI) - return 0; + goto no_pr; mpp = pp->mpp; if (!get_be64(mpp->reservation_key)) - return -1; + goto no_pr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -3876,4 +3881,8 @@ int mpath_pr_event_handle(struct path *pp) pthread_attr_destroy(&attr); rc = pthread_join(thread, NULL); return 0; + +no_pr: + pp->mpp->prflag = PRFLAG_UNSET; + return 0; } -- 2.17.2 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/dm-devel