Blob Blame History Raw
---
 libmultipath/discovery.c   |   10 ++++++--
 libmultipath/structs.h     |    1 
 libmultipath/structs_vec.c |    4 ++-
 multipathd/main.c          |   52 ++++++++++++++++++++++++++++++++-------------
 4 files changed, 49 insertions(+), 18 deletions(-)

Index: multipath-tools-130222/libmultipath/discovery.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/discovery.c
+++ multipath-tools-130222/libmultipath/discovery.c
@@ -1425,10 +1425,13 @@ pathinfo (struct path *pp, vector hwtabl
 		pp->fd = open(udev_device_get_devnode(pp->udev), O_RDONLY);
 
 	if (pp->fd < 0) {
+		pp->missing_udev_info = INFO_REINIT;
 		condlog(4, "Couldn't open node for %s: %s",
 			pp->dev, strerror(errno));
 		goto blank;
 	}
+	if (pp->missing_udev_info == INFO_REINIT)
+		pp->missing_udev_info = INFO_OK;
 
 	if (mask & DI_SERIAL)
 		get_geometry(pp);
@@ -1443,8 +1446,11 @@ pathinfo (struct path *pp, vector hwtabl
 
 	if (mask & DI_CHECKER) {
 		if (path_state == PATH_UP) {
-			pp->chkrstate = pp->state = get_state(pp, 0,
-							      path_state);
+			int newstate = get_state(pp, 0, path_state);
+			if (newstate != PATH_PENDING ||
+			    pp->state == PATH_UNCHECKED ||
+			    pp->state == PATH_WILD)
+				pp->chkrstate = pp->state = newstate;
 			if (pp->state == PATH_UNCHECKED ||
 			    pp->state == PATH_WILD)
 				goto blank;
Index: multipath-tools-130222/libmultipath/structs.h
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs.h
+++ multipath-tools-130222/libmultipath/structs.h
@@ -184,6 +184,7 @@ enum marginal_path_states {
 
 enum missing_udev_info_states {
 	INFO_OK,
+	INFO_REINIT,
 	INFO_MISSING,
 	INFO_REQUESTED,
 };
Index: multipath-tools-130222/multipathd/main.c
===================================================================
--- multipath-tools-130222.orig/multipathd/main.c
+++ multipath-tools-130222/multipathd/main.c
@@ -1381,7 +1381,7 @@ int update_path_groups(struct multipath
 	return 0;
 }
 
-void
+int
 check_path (struct vectors * vecs, struct path * pp)
 {
 	int newstate;
@@ -1390,19 +1390,20 @@ check_path (struct vectors * vecs, struc
 	int disable_reinstate = 0;
 	int oldchkrstate = pp->chkrstate;
 
-	if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING ||
-			 pp->retriggers >= conf->retrigger_tries))
-		return;
+	if (!pp->mpp && pp->missing_udev_info != INFO_REINIT &&
+	    (pp->missing_udev_info != INFO_MISSING ||
+	     pp->retriggers >= conf->retrigger_tries))
+		return 0;
 
 	if (pp->tick && --pp->tick)
-		return; /* don't check this path yet */
+		return 0; /* don't check this path yet */
 
-	if (!pp->mpp) {
+	if (!pp->mpp && pp->missing_udev_info == INFO_MISSING) {
 		pp->missing_udev_info = INFO_REQUESTED;
 		pp->retriggers++;
 		sysfs_attr_set_value(pp->udev, "uevent", "change",
 				     strlen("change"));
-		return;
+		return 0;
 	}
 
 	/*
@@ -1412,6 +1413,21 @@ check_path (struct vectors * vecs, struc
 	pp->tick = conf->checkint;
 
 	newstate = path_offline(pp);
+	if (!pp->mpp) {
+		if (newstate == PATH_UP &&
+		    pp->missing_udev_info == INFO_REINIT) {
+			int ret;
+			condlog(3, "%s: add missing path", pp->dev);
+			ret = pathinfo(pp, conf->hwtable,
+				       DI_ALL | DI_BLACKLIST);
+			if (ret == PATHINFO_OK && strlen(pp->wwid)) {
+				ev_add_path(pp, vecs);
+				pp->tick = 1;
+			} else if (ret == PATHINFO_SKIPPED)
+				return -1;
+		}
+		return 0;
+	}
 	if (newstate == PATH_UP)
 		newstate = get_state(pp, 1, newstate);
 	else
@@ -1426,7 +1442,7 @@ check_path (struct vectors * vecs, struc
 	if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
 		condlog(2, "%s: unusable path", pp->dev);
 		pathinfo(pp, conf->hwtable, 0);
-		return;
+		return 0;
 	}
 	/*
 	 * Async IO in flight. Keep the previous path state
@@ -1434,7 +1450,7 @@ check_path (struct vectors * vecs, struc
 	 */
 	if (newstate == PATH_PENDING) {
 		pp->tick = 1;
-		return;
+		return 0;
 	}
 	/*
 	 * Synchronize with kernel state
@@ -1446,7 +1462,7 @@ check_path (struct vectors * vecs, struc
 	}
 	/* if update_multipath_strings orphaned the path, quit early */
 	if (!pp->mpp)
-		return;
+		return 0;
 
 	if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
 	    pp->io_err_disable_reinstate && need_io_err_check(pp)) {
@@ -1456,7 +1472,7 @@ check_path (struct vectors * vecs, struc
 		 * be recoverd in time
 		 */
 		pp->tick = 1;
-		return;
+		return 0;
 	}
 
 	if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
@@ -1464,7 +1480,7 @@ check_path (struct vectors * vecs, struc
 		if (pp->mpp && pp->mpp->nr_active > 0) {
 			pp->state = PATH_DELAYED;
 			pp->wait_checks--;
-			return;
+			return 0;
 		} else
 			pp->wait_checks = 0;
 	}
@@ -1512,7 +1528,7 @@ check_path (struct vectors * vecs, struc
 			pp->mpp->failback_tick = 0;
 
 			pp->mpp->stat_path_failures++;
-			return;
+			return 0;
 		}
 
 		if(newstate == PATH_UP || newstate == PATH_GHOST){
@@ -1594,7 +1610,7 @@ check_path (struct vectors * vecs, struc
 
 
 	if (pp->mpp->wait_for_udev)
-		return;
+		return 0;
 	/*
 	 * path prio refreshing
 	 */
@@ -1613,6 +1629,7 @@ check_path (struct vectors * vecs, struc
 			 (chkr_new_path_up && followover_should_failback(pp)))
 			switch_pathgroup(pp->mpp);
 	}
+	return 0;
 }
 
 static void *
@@ -1642,7 +1659,12 @@ checkerloop (void *ap)
 
 		if (vecs->pathvec) {
 			vector_foreach_slot (vecs->pathvec, pp, i) {
-				check_path(vecs, pp);
+				int rc = check_path(vecs, pp);
+				if (rc < 0) {
+					vector_del_slot(vecs->pathvec, i);
+					free_path(pp);
+					i--;
+				}
 			}
 		}
 		if (vecs->mpvec) {
Index: multipath-tools-130222/libmultipath/structs_vec.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/structs_vec.c
+++ multipath-tools-130222/libmultipath/structs_vec.c
@@ -274,9 +274,11 @@ void sync_paths(struct multipath *mpp, v
 			}
 		}
 		if (!found) {
-			condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
+			condlog(2, "%s dropped path %s", mpp->alias, pp->dev);
 			vector_del_slot(mpp->paths, i--);
 			orphan_path(pp);
+			memset(pp->wwid, 0, WWID_SIZE);
+			pp->missing_udev_info = INFO_REINIT;
 		}
 	}
 	update_mpp_paths(mpp, pathvec);