--- libmpathpersist/mpath_persist.c | 28 +++++++++++--- libmultipath/config.c | 3 + libmultipath/config.h | 2 + libmultipath/defaults.h | 1 libmultipath/dict.c | 77 ++++++++++++++++++++++++++++++++++++++++ libmultipath/propsel.c | 20 ++++++++++ libmultipath/propsel.h | 1 libmultipath/structs.h | 7 +++ multipath/multipath.conf.5 | 7 +++ 9 files changed, 140 insertions(+), 6 deletions(-) Index: multipath-tools-130222-patched/libmpathpersist/mpath_persist.c =================================================================== --- multipath-tools-130222-patched.orig/libmpathpersist/mpath_persist.c +++ multipath-tools-130222-patched/libmpathpersist/mpath_persist.c @@ -287,6 +287,7 @@ int mpath_persistent_reserve_out ( int f } select_reservation_key(mpp); + select_all_tg_pt(mpp); memcpy(&prkey, paramp->sa_key, 8); if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey && @@ -419,7 +420,7 @@ int mpath_prout_reg(struct multipath *mp unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy) { - int i, j; + int i, j, k; struct pathgroup *pgp = NULL; struct path *pp = NULL; int rollback = 0; @@ -444,11 +445,13 @@ int mpath_prout_reg(struct multipath *mp } struct threadinfo thread[active_pathcount]; + int hosts[active_pathcount]; memset(thread, 0, sizeof(thread)); /* init thread parameter */ for (i =0; i< active_pathcount; i++){ + hosts[i] = -1; thread[i].param.rq_servact = rq_servact; thread[i].param.rq_scope = rq_scope; thread[i].param.rq_type = rq_type; @@ -476,6 +479,17 @@ int mpath_prout_reg(struct multipath *mp condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev); continue; } + if (mpp->all_tg_pt == ALL_TG_PT_ON && + pp->sg_id.host_no != -1) { + for (k = 0; k < count; k++) { + if (pp->sg_id.host_no == hosts[k]) { + condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no); + break; + } + } + if (k < count) + continue; + } strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE); if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){ @@ -492,10 +506,12 @@ int mpath_prout_reg(struct multipath *mp condlog (0, "%s: failed to create thread %d", mpp->wwid, rc); thread[count].param.status = MPATH_PR_THREAD_ERROR; } + else + hosts[count] = pp->sg_id.host_no; count = count +1; } } - for( i=0; i < active_pathcount ; i++){ + for( i=0; i < count ; i++){ if (thread[i].param.status != MPATH_PR_THREAD_ERROR) { rc = pthread_join(thread[i].id, NULL); if (rc){ @@ -518,7 +534,7 @@ int mpath_prout_reg(struct multipath *mp } if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){ condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid); - for( i=0 ; i < active_pathcount ; i++){ + for( i=0 ; i < count ; i++){ if (thread[i].param.status == MPATH_PR_SUCCESS) { memcpy(&thread[i].param.paramp->key, &thread[i].param.paramp->sa_key, 8); memset(&thread[i].param.paramp->sa_key, 0, 8); @@ -532,7 +548,7 @@ int mpath_prout_reg(struct multipath *mp } else thread[i].param.status = MPATH_PR_SKIP; } - for(i=0; i < active_pathcount ; i++){ + for(i=0; i < count ; i++){ if (thread[i].param.status != MPATH_PR_SKIP && thread[i].param.status != MPATH_PR_THREAD_ERROR) { rc = pthread_join(thread[i].id, NULL); @@ -678,7 +694,7 @@ int mpath_prout_rel(struct multipath *mp } } pthread_attr_destroy (&attr); - for (i = 0; i < active_pathcount; i++){ + for (i = 0; i < count; i++){ if (thread[i].param.status != MPATH_PR_THREAD_ERROR) { rc = pthread_join (thread[i].id, NULL); if (rc){ @@ -687,7 +703,7 @@ int mpath_prout_rel(struct multipath *mp } } - for (i = 0; i < active_pathcount; i++){ + for (i = 0; i < count; i++){ /* check thread status here and return the status */ if (thread[i].param.status == MPATH_PR_RESERV_CONFLICT) Index: multipath-tools-130222-patched/libmultipath/config.c =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/config.c +++ multipath-tools-130222-patched/libmultipath/config.c @@ -349,6 +349,7 @@ merge_hwe (struct hwentry * dst, struct merge_num(max_sectors_kb); merge_num(unpriv_sgio); merge_num(ghost_delay); + merge_num(all_tg_pt); /* * Make sure features is consistent with @@ -414,6 +415,7 @@ overwrite_hwe (struct hwentry * dst, str overwrite_num(max_sectors_kb); overwrite_num(unpriv_sgio); overwrite_num(ghost_delay); + overwrite_num(all_tg_pt); /* * Make sure features is consistent with @@ -700,6 +702,7 @@ load_config (char * file, struct udev *u conf->max_sectors_kb = DEFAULT_MAX_SECTORS_KB; conf->unpriv_sgio = DEFAULT_UNPRIV_SGIO; conf->ghost_delay = DEFAULT_GHOST_DELAY; + conf->all_tg_pt = DEFAULT_ALL_TG_PT; /* * preload default hwtable Index: multipath-tools-130222-patched/libmultipath/config.h =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/config.h +++ multipath-tools-130222-patched/libmultipath/config.h @@ -71,6 +71,7 @@ struct hwentry { int max_sectors_kb; int unpriv_sgio; int ghost_delay; + int all_tg_pt; char * bl_product; }; @@ -162,6 +163,7 @@ struct config { int max_sectors_kb; int unpriv_sgio; int ghost_delay; + int all_tg_pt; unsigned int version[3]; char * dev; Index: multipath-tools-130222-patched/libmultipath/dict.c =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/dict.c +++ multipath-tools-130222-patched/libmultipath/dict.c @@ -1051,6 +1051,29 @@ def_ghost_delay_handler(vector strvec) return 0; } +static int +def_all_tg_pt_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->all_tg_pt = ALL_TG_PT_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + conf->all_tg_pt = ALL_TG_PT_ON; + else + conf->all_tg_pt = DEFAULT_ALL_TG_PT; + + FREE(buff); + return 0; +} + + /* * blacklist block handlers */ @@ -1969,6 +1992,33 @@ hw_ghost_delay_handler(vector strvec) return 0; } +static int +hw_all_tg_pt_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->all_tg_pt = ALL_TG_PT_OFF; + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || + (strlen(buff) == 1 && !strcmp(buff, "1"))) + hwe->all_tg_pt = ALL_TG_PT_ON; + else + hwe->all_tg_pt = ALL_TG_PT_UNDEF; + + FREE(buff); + return 0; +} + /* * multipaths block handlers */ @@ -3325,6 +3375,19 @@ snprint_hw_ghost_delay (char * buff, int } static int +snprint_hw_all_tg_pt(char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + if (hwe->all_tg_pt == ALL_TG_PT_ON) + return snprintf(buff, len, "yes"); + else if (hwe->all_tg_pt == ALL_TG_PT_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); @@ -3829,6 +3892,15 @@ snprint_def_ghost_delay (char * buff, in } static int +snprint_def_all_tg_pt(char * buff, int len, void * data) +{ + if (conf->all_tg_pt == ALL_TG_PT_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; @@ -3926,6 +3998,7 @@ init_keywords(void) install_keyword("max_sectors_kb", &def_max_sectors_kb_handler, &snprint_def_max_sectors_kb); install_keyword("unpriv_sgio", &def_unpriv_sgio_handler, &snprint_def_unpriv_sgio); install_keyword("ghost_delay", &def_ghost_delay_handler, &snprint_def_ghost_delay); + install_keyword("all_tg_pt", &def_all_tg_pt_handler, &snprint_def_all_tg_pt); __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); @@ -4000,6 +4073,7 @@ init_keywords(void) install_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb); install_keyword("unpriv_sgio", &hw_unpriv_sgio_handler, &snprint_hw_unpriv_sgio); install_keyword("ghost_delay", &hw_ghost_delay_handler, &snprint_hw_ghost_delay); + install_keyword("all_tg_pt", &hw_all_tg_pt_handler, &snprint_hw_all_tg_pt); install_sublevel_end(); install_keyword_root("overrides", &nop_handler); @@ -4031,6 +4105,9 @@ init_keywords(void) install_keyword("delay_wait_checks", &nop_handler, &snprint_nop); install_keyword("skip_kpartx", &nop_handler, &snprint_nop); install_keyword("max_sectors_kb", &nop_handler, &snprint_nop); + install_keyword("unpriv_sgio", &nop_handler, &snprint_nop); + install_keyword("ghost_delay", &nop_handler, &snprint_nop); + install_keyword("all_tg_pt", &nop_handler, &snprint_nop); install_keyword_root("multipaths", &multipaths_handler); install_keyword_multi("multipath", &multipath_handler, NULL); Index: multipath-tools-130222-patched/libmultipath/propsel.c =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/propsel.c +++ multipath-tools-130222-patched/libmultipath/propsel.c @@ -992,3 +992,23 @@ select_ghost_delay (struct multipath * m condlog(3, "ghost_delay = DISABLED (internal default)"); return 0; } + +extern int +select_all_tg_pt (struct multipath *mp) +{ + if (mp->hwe && mp->hwe->all_tg_pt != ALL_TG_PT_UNDEF) { + mp->all_tg_pt = mp->hwe->all_tg_pt; + condlog(3, "all_tg_pt = %i (controller setting)", + mp->all_tg_pt); + return 0; + } + if (conf->all_tg_pt != GHOST_DELAY_UNDEF) { + mp->all_tg_pt = conf->all_tg_pt; + condlog(3, "all_tg_pt = %i (config file default)", + mp->all_tg_pt); + return 0; + } + mp->all_tg_pt = DEFAULT_ALL_TG_PT; + condlog(3, "all_tg_pt = %i (internal default)", mp->all_tg_pt); + return 0; +} Index: multipath-tools-130222-patched/libmultipath/structs.h =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/structs.h +++ multipath-tools-130222-patched/libmultipath/structs.h @@ -154,6 +154,12 @@ enum unpriv_sgio_states { UNPRIV_SGIO_ON, }; +enum all_tg_pt_states { + ALL_TG_PT_UNDEF, + ALL_TG_PT_OFF, + ALL_TG_PT_ON, +}; + enum scsi_protocol { SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ @@ -324,6 +330,7 @@ struct multipath { int prkey_source; struct be64 reservation_key; unsigned char prflag; + int all_tg_pt; }; struct pathgroup { Index: multipath-tools-130222-patched/libmultipath/propsel.h =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/propsel.h +++ multipath-tools-130222-patched/libmultipath/propsel.h @@ -28,3 +28,4 @@ int select_skip_kpartx (struct multipath int select_max_sectors_kb (struct multipath * mp); int select_unpriv_sgio (struct multipath * mp); int select_ghost_delay (struct multipath * mp); +int select_all_tg_pt (struct multipath *mp); Index: multipath-tools-130222-patched/libmultipath/defaults.h =================================================================== --- multipath-tools-130222-patched.orig/libmultipath/defaults.h +++ multipath-tools-130222-patched/libmultipath/defaults.h @@ -29,6 +29,7 @@ #define DEFAULT_MAX_SECTORS_KB MAX_SECTORS_KB_UNDEF #define DEFAULT_UNPRIV_SGIO UNPRIV_SGIO_OFF #define DEFAULT_GHOST_DELAY GHOST_DELAY_OFF +#define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF #define DEFAULT_CHECKINT 5 #define MAX_CHECKINT(a) (a << 2) Index: multipath-tools-130222-patched/multipath/multipath.conf.5 =================================================================== --- multipath-tools-130222-patched.orig/multipath/multipath.conf.5 +++ multipath-tools-130222-patched/multipath/multipath.conf.5 @@ -449,6 +449,13 @@ registration is removed, the RESERVATION It is unset by default. .RE .TP +.B all_tg_pt +This must be set to \fIyes\fR to successfully use mpathpersist on arrays that +automatically set and clear registration keys on all target ports from a +host, instead of per target port per host. +Default is +.I no +.TP .B retain_attached_hw_handler If set to .I yes