--- libmultipath/config.c | 3 + libmultipath/config.h | 2 + libmultipath/configure.c | 7 +++- libmultipath/defaults.h | 1 libmultipath/dict.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ libmultipath/dmparser.c | 3 + libmultipath/propsel.c | 17 ++++++++++ libmultipath/propsel.h | 1 libmultipath/structs.h | 7 ++++ 9 files changed, 113 insertions(+), 2 deletions(-) Index: multipath-tools-120821/libmultipath/config.c =================================================================== --- multipath-tools-120821.orig/libmultipath/config.c +++ multipath-tools-120821/libmultipath/config.c @@ -327,6 +327,7 @@ merge_hwe (struct hwentry * dst, struct merge_num(fast_io_fail); merge_num(dev_loss); merge_num(user_friendly_names); + merge_num(retain_hwhandler); return 0; } @@ -386,6 +387,7 @@ store_hwe (vector hwtable, struct hwentr hwe->fast_io_fail = dhwe->fast_io_fail; hwe->dev_loss = dhwe->dev_loss; hwe->user_friendly_names = dhwe->user_friendly_names; + hwe->retain_hwhandler = dhwe->retain_hwhandler; if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product))) goto out; @@ -519,6 +521,7 @@ load_config (char * file) conf->max_checkint = MAX_CHECKINT(conf->checkint); conf->find_multipaths = DEFAULT_FIND_MULTIPATHS; conf->fast_io_fail = 5; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; /* * preload default hwtable Index: multipath-tools-120821/libmultipath/config.h =================================================================== --- multipath-tools-120821.orig/libmultipath/config.h +++ multipath-tools-120821/libmultipath/config.h @@ -46,6 +46,7 @@ struct hwentry { int fast_io_fail; unsigned int dev_loss; int user_friendly_names; + int retain_hwhandler; char * bl_product; }; @@ -110,6 +111,7 @@ struct config { mode_t mode; uint32_t cookie; int reassign_maps; + int retain_hwhandler; char * dev; struct udev * udev; Index: multipath-tools-120821/libmultipath/defaults.h =================================================================== --- multipath-tools-120821.orig/libmultipath/defaults.h +++ multipath-tools-120821/libmultipath/defaults.h @@ -16,6 +16,7 @@ #define DEFAULT_VERBOSITY 2 #define DEFAULT_REASSIGN_MAPS 1 #define DEFAULT_FIND_MULTIPATHS 0 +#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF #define DEFAULT_CHECKINT 5 #define MAX_CHECKINT(a) (a << 2) Index: multipath-tools-120821/libmultipath/dict.c =================================================================== --- multipath-tools-120821.orig/libmultipath/dict.c +++ multipath-tools-120821/libmultipath/dict.c @@ -650,6 +650,29 @@ wwids_file_handler(vector strvec) return 0; } +static int +def_retain_hwhandler_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + + if (!buff) + return 1; + + if ((strlen(buff) == 2 && !strcmp(buff, "no")) || + (strlen(buff) == 1 && !strcmp(buff, "0"))) + conf->retain_hwhandler = RETAIN_HWHANDLER_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + conf->retain_hwhandler = RETAIN_HWHANDLER_ON; + else + conf->retain_hwhandler = RETAIN_HWHANDLER_UNDEF; + + FREE(buff); + return 0; +} + /* * blacklist block handlers */ @@ -1271,6 +1294,33 @@ hw_names_handler(vector strvec) return 0; } +static int +hw_retain_hwhandler_handler(vector strvec) +{ + struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); + char * buff; + + if (!hwe) + return 1; + + buff = set_value(strvec); + + if (!buff) + return 1; + + if ((strlen(buff) == 2 && !strcmp(buff, "no")) || + (strlen(buff) == 1 && !strcmp(buff, "0"))) + hwe->retain_hwhandler = RETAIN_HWHANDLER_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + hwe->retain_hwhandler = RETAIN_HWHANDLER_ON; + else + hwe->user_friendly_names = RETAIN_HWHANDLER_UNDEF; + + FREE(buff); + return 0; +} + /* * multipaths block handlers */ @@ -2295,6 +2345,19 @@ snprint_hw_user_friendly_names (char * b } static int +snprint_hw_retain_hwhandler_handler(char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (hwe->retain_hwhandler == RETAIN_HWHANDLER_ON) + return snprintf(buff, len, "yes"); + else if (hwe->retain_hwhandler == RETAIN_HWHANDLER_OFF) + return snprintf(buff, len, "no"); + else + return 0; +} + +static int snprint_def_polling_interval (char * buff, int len, void * data) { return snprintf(buff, len, "%i", conf->checkint); @@ -2632,6 +2695,15 @@ snprint_def_reservation_key(char * buff, } static int +snprint_def_retain_hwhandler_handler(char * buff, int len, void * data) +{ + if (conf->retain_hwhandler == RETAIN_HWHANDLER_ON) + return snprintf(buff, len, "yes"); + else + return snprintf(buff, len, "no"); +} + +static int snprint_ble_simple (char * buff, int len, void * data) { struct blentry * ble = (struct blentry *)data; @@ -2696,6 +2768,7 @@ init_keywords(void) install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths); + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); __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); @@ -2757,6 +2830,7 @@ init_keywords(void) install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail); install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss); install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names); + install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler); install_sublevel_end(); install_keyword_root("multipaths", &multipaths_handler); Index: multipath-tools-120821/libmultipath/structs.h =================================================================== --- multipath-tools-120821.orig/libmultipath/structs.h +++ multipath-tools-120821/libmultipath/structs.h @@ -99,6 +99,12 @@ enum user_friendly_names_states { USER_FRIENDLY_NAMES_ON, }; +enum retain_hwhandler_states { + RETAIN_HWHANDLER_UNDEF, + RETAIN_HWHANDLER_OFF, + RETAIN_HWHANDLER_ON, +}; + struct scsi_idlun { int dev_id; int host_unique_id; @@ -188,6 +194,7 @@ struct multipath { int flush_on_last_del; int attribute_flags; int fast_io_fail; + int retain_hwhandler; unsigned int dev_loss; uid_t uid; gid_t gid; Index: multipath-tools-120821/libmultipath/configure.c =================================================================== --- multipath-tools-120821.orig/libmultipath/configure.c +++ multipath-tools-120821/libmultipath/configure.c @@ -76,6 +76,7 @@ setup_map (struct multipath * mpp, char select_fast_io_fail(mpp); select_dev_loss(mpp); select_reservation_key(mpp); + select_retain_hwhandler(mpp); sysfs_set_scsi_tmo(mpp); /* @@ -217,8 +218,10 @@ select_action (struct multipath * mpp, v mpp->alias); return; } - if (!cmpp->selector || strncmp(cmpp->hwhandler, mpp->hwhandler, - strlen(mpp->hwhandler))) { + if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON && + (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) || + strncmp(cmpp->hwhandler, mpp->hwhandler, + strlen(mpp->hwhandler)))) { mpp->action = ACT_RELOAD; condlog(3, "%s: set ACT_RELOAD (hwhandler change)", mpp->alias); Index: multipath-tools-120821/libmultipath/dmparser.c =================================================================== --- multipath-tools-120821.orig/libmultipath/dmparser.c +++ multipath-tools-120821/libmultipath/dmparser.c @@ -56,6 +56,7 @@ assemble_map (struct multipath * mp, cha int nr_priority_groups, initial_pg_nr; char * p, * f; char no_path_retry[] = "queue_if_no_path"; + char retain_hwhandler[] = "retain_attached_hw_handler"; struct pathgroup * pgp; struct path * pp; @@ -81,6 +82,8 @@ assemble_map (struct multipath * mp, cha } else { add_feature(&f, no_path_retry); } + if (mp->retain_hwhandler == RETAIN_HWHANDLER_ON) + add_feature(&f, retain_hwhandler); shift = snprintf(p, freechar, "%s %s %i %i", f, mp->hwhandler, Index: multipath-tools-120821/libmultipath/propsel.c =================================================================== --- multipath-tools-120821.orig/libmultipath/propsel.c +++ multipath-tools-120821/libmultipath/propsel.c @@ -674,3 +674,20 @@ select_reservation_key (struct multipath return 0; } +extern int +select_retain_hwhandler (struct multipath * mp) +{ + if (mp->hwe && mp->hwe->retain_hwhandler) { + mp->retain_hwhandler = mp->hwe->retain_hwhandler; + condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler); + return 0; + } + if (conf->retain_hwhandler) { + mp->retain_hwhandler = conf->retain_hwhandler; + condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler); + return 0; + } + mp->retain_hwhandler = 0; + condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler); + return 0; +} Index: multipath-tools-120821/libmultipath/propsel.h =================================================================== --- multipath-tools-120821.orig/libmultipath/propsel.h +++ multipath-tools-120821/libmultipath/propsel.h @@ -18,3 +18,4 @@ int select_gid(struct multipath *mp); int select_fast_io_fail(struct multipath *mp); int select_dev_loss(struct multipath *mp); int select_reservation_key(struct multipath *mp); +extern int select_retain_hwhandler (struct multipath * mp);