[dm-devel] [PATCH 3/6] multipathd: handle no active paths in update_map_pr

Benjamin Marzinski bmarzins at redhat.com
Tue Dec 20 23:41:12 UTC 2022


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 at redhat.com>
---
 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



More information about the dm-devel mailing list