--- 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);