[dm-devel] [PATCH 2/6] fix lun expansion failure when there is offline path

lixiaokeng lixiaokeng at huawei.com
Mon Oct 26 09:25:26 UTC 2020


There are two paths for one multipath device; one path
is up and the other path is down. Expand the multipath
device in server. Scan the path size in client. It will
cause failure expansion in client. The reason:
When two different-size paths for one device pass to
kernel. Kerenl will return fail. Multipathd will try to
delete the multipath device but fail because the
device is used. Here we check the offline path; if its'
size is different with other path, delete it.

Signed-off-by: Yanfei Zhang <yanfei.zhang at huawei.com>
Signed-off-by: Lixiaokeng <lixiaokeng at huawei.com>
---
 libmultipath/configure.c   | 18 ++++++++++++++++++
 libmultipath/structs.c     |  1 +
 libmultipath/structs.h     |  1 +
 libmultipath/structs_vec.c |  6 ++++--
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 9d6eeba1..00c12929 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1176,6 +1176,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,

 	vector_foreach_slot (pathvec, pp1, k) {
 		int invalid;
+		condlog(3, "%s %s: start coalesce", pp1->dev, pp1->dev_t);
 		/* skip this path for some reason */

 		/* 1. if path has no unique id or wwid blacklisted */
@@ -1213,6 +1214,18 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
 			continue;
 		}

+		/* if path is offline */
+		if (pp1->state == PATH_DOWN) {
+			orphan_path(pp1, "skip offline path");
+			continue;
+		}
+
+		/* if path is handled before */
+		if (pp1->handled) {
+			condlog(3, "%s: skip handled path.", pp1->dev_t);
+			continue;
+		}
+
 		/*
 		 * at this point, we know we really got a new mp
 		 */
@@ -1230,10 +1243,15 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,

 		for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
 			pp2 = VECTOR_SLOT(pathvec, i);
+			if (pp2->handled)
+				continue;

 			if (strcmp(pp1->wwid, pp2->wwid))
 				continue;

+			if (!pp2->size || pp2->state == PATH_DOWN)
+				continue;
+
 			if (!mpp->size && pp2->size)
 				mpp->size = pp2->size;

diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 464596fc..e5de0a7d 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -101,6 +101,7 @@ alloc_path (void)
 		pp->fd = -1;
 		pp->tpgs = TPGS_UNDEF;
 		pp->priority = PRIO_UNDEF;
+		pp->handled = 0;
 		pp->checkint = CHECKINT_UNDEF;
 		checker_clear(&pp->checker);
 		dm_path_to_gen(pp)->ops = &dm_gen_path_ops;
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 7de93d6c..022ba126 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -280,6 +280,7 @@ struct path {
 	struct checker checker;
 	struct multipath * mpp;
 	int fd;
+	int handled;
 	int initialized;
 	int retriggers;
 	unsigned int path_failures;
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 8895fa77..5a73d4ce 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -738,11 +738,13 @@ int verify_paths(struct multipath *mpp)
 		return 0;

 	vector_foreach_slot (mpp->paths, pp, i) {
+		pp->handled = 1;
 		/*
 		 * see if path is in sysfs
 		 */
-		if (!pp->udev || sysfs_attr_get_value(pp->udev, "dev",
-					 pp->dev_t, BLK_DEV_SIZE) < 0) {
+		if ((!pp->udev || sysfs_attr_get_value(pp->udev, "dev",
+		    pp->dev_t, BLK_DEV_SIZE) < 0) ||
+		    (pp->state == PATH_DOWN && pp->size != mpp->size)) {
 			if (pp->state != PATH_DOWN) {
 				condlog(1, "%s: removing valid path %s in state %d",
 					mpp->alias, pp->dev, pp->state);
-- 




More information about the dm-devel mailing list