[dm-devel] multipathd: fix check_path could not resume path state

wangjufeng wangjufeng at huawei.com
Sat Mar 21 15:53:42 UTC 2020


>From fb655da18aefccaa09c70036b08c88a03609ec45 Mon Sep 17 00:00:00 2001
From: wangjufeng <wangjufeng at huawei.com>
Date: Sat, 21 Mar 2020 22:23:10 +0800
Subject: [PATCH] multipathd: fix check_path could not resume path state

For some unknown reason, after network recovery from disconnection,
the paths in a multipath are still in fail state. Use gdb attached
multipathd, the paths seem to be changed by orphan_path function,
pp->initialized is INIT_OK while pp->mpp is NULL, pp->dmstate is
PSTATE_UNDEF, pp->fd is -1. And the multipath could not be found in
gvecs->mpvec while it could be found by dmsetup table command.

It will lead to that the path state could not be activated by
check_path even if the iscsi device is already available.

This patch intend to add the multipath map again to avoid IO failure
or IO blocked when the above phenomenon occur.

Signed-off-by: wangjufeng <wangjufeng at huawei.com>
Reviewed-by: linfeilong <linfeilong at huawei.com>
---
 multipathd/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/multipathd/main.c b/multipathd/main.c
index 8baf9ab..4ca622c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1962,10 +1962,59 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
 	struct config *conf;
 	int marginal_pathgroups, marginal_changed = 0;
 	int ret;
+	char *param;
+        int major;
+        int minor;
+        int invalid = 0;
+        char dev_path[PATH_SIZE];
+        char *alias = NULL;
+	struct multipath *mpp;
 
 	if ((pp->initialized == INIT_OK ||
-	     pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp)
-		return 0;
+	     pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp) {
+		if (pp->initialized == INIT_OK && !pp->mpp &&
+		    pp->dmstate == PSTATE_UNDEF && pp->fd == -1) {
+			mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
+			if (mpp != NULL) {
+				return 0;
+			}
+			/*
+			 * If a multipath is not in gvecs->mpvec, while it could be found in
+			 * device-mapper devices. It should be mapped again, or multipathd
+			 * can not add it again because of that check_path early return.
+			 */
+			param = convert_dev(pp->wwid, 0);
+			conf = get_multipath_config();
+			pthread_cleanup_push(put_multipath_config, conf);
+			if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0) {
+				invalid = 1;
+			}
+			pthread_cleanup_pop(1);
+			if (invalid) {
+				condlog(2, "%s: map blacklisted", param);
+				return 0;
+			}
+
+			if (dm_get_major_minor(param, &major, &minor) < 0) {
+				return 0;
+			} else {
+				sprintf(dev_path, "dm-%d", minor);
+				alias = dm_mapname(major, minor);
+				if (!alias) {
+					condlog(2, "fail to get alias of %s %d:%d", param, major, minor);
+					return 0;
+				}
+				if (ev_add_map(dev_path, alias, vecs)) {
+					condlog(2, "fail to add map for mpp %s", alias);
+					return 0;
+				} else {
+					condlog(2, "success to add map for mpp %s", alias);
+				}
+			}
+		} else {
+			return 0;
+		}
+	}
 
 	if (pp->tick)
 		pp->tick -= (pp->tick > ticks) ? ticks : pp->tick;
-- 
1.8.3.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: multipathd-fix-check_path-could-not-resume-path-stat.patch
Type: application/octet-stream
Size: 3112 bytes
Desc: multipathd-fix-check_path-could-not-resume-path-stat.patch
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20200321/06fa486f/attachment.obj>


More information about the dm-devel mailing list