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@xxxxxxxxxx> Signed-off-by: Lixiaokeng <lixiaokeng@xxxxxxxxxx> --- 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); -- -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel