The same LUN have been exported to the host from different lun number twice, each time create multipath for this lun, after second time the multipath might have zombie paths which devices doesn't actually exist. Check zombie paths: If a failed path have the same wwid with an active path, but its sg_id.lun are not equal to this active path. This failed path might be a zombie path(a lun can't be exported from a different lun number to a host at the same time). cleanup zombie paths: delete the zombie paths' device from sysfs, which will clean up the zombie paths both in kernel and userspace. Signed-off-by: Chongyun Wu <wu.chongyun@xxxxxxx> --- multipathd/main.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/multipathd/main.c b/multipathd/main.c index 27cf234..e74a448 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -1511,6 +1511,44 @@ void repair_path(struct path * pp) LOG_MSG(1, checker_message(&pp->checker)); } +void try_cleanup_zombie_path(struct vectors *vecs, struct path *pp) +{ + struct path *pp_tmp; + unsigned int i; + struct config *conf; + int path_state; + const char delete[] = "1"; + + /*check if this given path is a zombie path*/ + vector_foreach_slot(vecs->pathvec, pp_tmp, i) { + if ((strcmp(pp_tmp->wwid, pp->wwid) == 0) && + (pp_tmp->state == PATH_UP)) { + /*to get the state again to avoid getting + *the old state + */ + conf = get_multipath_config(); + path_state = get_state(pp_tmp, conf, 1); + put_multipath_config(conf); + + if ((path_state == PATH_UP) && + (pp_tmp->sg_id.lun != pp->sg_id.lun)) { + /* + * The given path is a failed path, + * found a active path with the same wwid and + * it's sg_id.lun isn't equal to the given path, + * that means that the given is a zombie path! + * Clean up zombie path then. + */ + condlog(2, "clean up zombie path %s(%s)", + pp->dev, pp->wwid); + sysfs_attr_set_value(pp->udev, "device/delete", + delete, strlen(delete)); + break; + } + } + } +} + /* * Returns '1' if the path has been checked, '-1' if it was blacklisted * and '0' otherwise @@ -1580,6 +1618,10 @@ check_path (struct vectors * vecs, struct path * pp, int ticks) newstate = PATH_DOWN; } + if (newstate == PATH_DOWN) { + try_cleanup_zombie_path(vecs, pp); + } + if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) { condlog(2, "%s: unusable path", pp->dev); conf = get_multipath_config(); -- 1.7.9.5 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel