--- libmultipath/config.c | 2 ++ libmultipath/config.h | 2 ++ libmultipath/defaults.h | 2 ++ libmultipath/dict.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ libmultipath/discovery.c | 8 +++++--- libmultipath/structs.h | 8 ++++++++ multipathd/main.c | 15 ++++++++++++++- 7 files changed, 79 insertions(+), 4 deletions(-) Index: multipath-tools-130222/libmultipath/config.c =================================================================== --- multipath-tools-130222.orig/libmultipath/config.c +++ multipath-tools-130222/libmultipath/config.c @@ -673,6 +673,8 @@ load_config (char * file, struct udev *u conf->force_sync = 0; conf->ignore_new_boot_devs = 0; conf->processed_main_config = 0; + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; /* * preload default hwtable Index: multipath-tools-130222/libmultipath/config.h =================================================================== --- multipath-tools-130222.orig/libmultipath/config.h +++ multipath-tools-130222/libmultipath/config.h @@ -139,6 +139,8 @@ struct config { int processed_main_config; int delay_watch_checks; int delay_wait_checks; + int retrigger_tries; + int retrigger_delay; unsigned int version[3]; char * dev; Index: multipath-tools-130222/libmultipath/defaults.h =================================================================== --- multipath-tools-130222.orig/libmultipath/defaults.h +++ multipath-tools-130222/libmultipath/defaults.h @@ -21,6 +21,8 @@ #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF #define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF +#define DEFAULT_RETRIGGER_DELAY 10 +#define DEFAULT_RETRIGGER_TRIES 3 #define DEFAULT_CHECKINT 5 #define MAX_CHECKINT(a) (a << 2) Index: multipath-tools-130222/libmultipath/dict.c =================================================================== --- multipath-tools-130222.orig/libmultipath/dict.c +++ multipath-tools-130222/libmultipath/dict.c @@ -839,6 +839,38 @@ def_delay_wait_checks_handler(vector str return 0; } +static int +def_retrigger_tries_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + + if (!buff) + return 1; + + conf->retrigger_tries = atoi(buff); + FREE(buff); + + return 0; +} + +static int +def_retrigger_delay_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + + if (!buff) + return 1; + + conf->retrigger_delay = atoi(buff); + FREE(buff); + + return 0; +} + /* * blacklist block handlers */ @@ -3194,6 +3226,18 @@ snprint_def_delay_wait_checks(char * buf } static int +snprint_def_retrigger_tries (char * buff, int len, void * data) +{ + return snprintf(buff, len, "%i", conf->retrigger_tries); +} + +static int +snprint_def_retrigger_delay (char * buff, int len, void * data) +{ + return snprintf(buff, len, "%i", conf->retrigger_delay); +} + +static int snprint_ble_simple (char * buff, int len, void * data) { struct blentry * ble = (struct blentry *)data; @@ -3267,6 +3311,8 @@ init_keywords(void) install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks); install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); + install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); + install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); __deprecated install_keyword("default_selector", &def_selector_handler, NULL); __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); Index: multipath-tools-130222/libmultipath/discovery.c =================================================================== --- multipath-tools-130222.orig/libmultipath/discovery.c +++ multipath-tools-130222/libmultipath/discovery.c @@ -1111,9 +1111,13 @@ get_uid (struct path * pp) len = strlen(value); } strncpy(pp->wwid, value, len); + pp->missing_udev_info = INFO_OK; + pp->tick = 0; } else { condlog(3, "%s: no %s attribute", pp->dev, pp->uid_attribute); + pp->missing_udev_info = INFO_MISSING; + pp->tick = conf->retrigger_delay; } /* Strip any trailing blanks */ @@ -1201,10 +1205,8 @@ pathinfo (struct path *pp, vector hwtabl * Retrieve path priority, even for PATH_DOWN paths if it has never * been successfully obtained before. */ - if ((mask & DI_PRIO) && path_state == PATH_UP) { + if ((mask & DI_PRIO) && path_state == PATH_UP && strlen(pp->wwid)) { if (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF) { - if (!strlen(pp->wwid)) - get_uid(pp); get_prio(pp); } } Index: multipath-tools-130222/libmultipath/structs.h =================================================================== --- multipath-tools-130222.orig/libmultipath/structs.h +++ multipath-tools-130222/libmultipath/structs.h @@ -139,6 +139,12 @@ enum delay_checks_states { DELAY_CHECKS_UNDEF = 0, }; +enum missing_udev_info_states { + INFO_OK, + INFO_MISSING, + INFO_REQUESTED, +}; + struct sg_id { int host_no; int channel; @@ -193,6 +199,8 @@ struct path { struct checker checker; struct multipath * mpp; int fd; + int missing_udev_info; + int retriggers; /* configlet pointers */ struct hwentry * hwe; Index: multipath-tools-130222/multipathd/main.c =================================================================== --- multipath-tools-130222.orig/multipathd/main.c +++ multipath-tools-130222/multipathd/main.c @@ -708,6 +708,10 @@ uev_update_path (struct uevent *uev, str uev->kernel); return 1; } + + if (pp->missing_udev_info == INFO_REQUESTED) + return uev_add_path(uev, vecs); + /* reinit the prio values on change event, in case something is * different */ prio_init(&pp->prio); @@ -1133,12 +1137,21 @@ check_path (struct vectors * vecs, struc int chkr_new_path_up = 0; int oldchkrstate = pp->chkrstate; - if (!pp->mpp) + if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING || + pp->retriggers >= conf->retrigger_tries)) return; if (pp->tick && --pp->tick) return; /* don't check this path yet */ + if (!pp->mpp) { + pp->missing_udev_info = INFO_REQUESTED; + pp->retriggers++; + sysfs_attr_set_value(pp->udev, "uevent", "change", + strlen("change")); + return; + } + /* * provision a next check soonest, * in case we exit abnormaly from here