CVSROOT: /cvs/dm Module name: multipath-tools Branch: RHEL5_FC6 Changes by: bmarzins@xxxxxxxxxxxxxx 2008-09-04 20:09:48 Modified files: . : multipath.conf.annotated multipath.conf.synthetic libmultipath : config.c config.h dict.c propsel.c propsel.h structs.h structs_vec.c multipathd : cli.c cli.h cli_handlers.c cli_handlers.h main.c Log message: Fix fox bz #238421. You can now set flush_on_last_del in /etc/multipath.conf, which turns off queue_if_no_path when the last path is deleted from a multipath map. You can also manually disable and restore queueing with the multipathd interactive disablequeueing and restorequeueing commands. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipath.conf.annotated.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.18.2.7&r2=1.18.2.8 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipath.conf.synthetic.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.11.2.4&r2=1.11.2.5 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/config.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.19.2.6&r2=1.19.2.7 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/config.h.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.18.2.5&r2=1.18.2.6 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/dict.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.17.2.6&r2=1.17.2.7 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/propsel.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.11.2.1&r2=1.11.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/propsel.h.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.5.2.1&r2=1.5.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/structs.h.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.18.2.4&r2=1.18.2.5 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libmultipath/structs_vec.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.1.2.2&r2=1.1.2.3 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipathd/cli.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.5.2.1&r2=1.5.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipathd/cli.h.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.5.2.1&r2=1.5.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipathd/cli_handlers.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.6.2.1&r2=1.6.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipathd/cli_handlers.h.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.3.2.1&r2=1.3.2.2 http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/multipathd/main.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.69.2.9&r2=1.69.2.10 --- multipath-tools/multipath.conf.annotated 2008/08/29 21:30:34 1.18.2.7 +++ multipath-tools/multipath.conf.annotated 2008/09/04 20:09:48 1.18.2.8 @@ -121,6 +121,15 @@ # # # #no_path_retry queue # +# # name : flush_on_last_del +# # scope : multipathd +# # desc : If set to "yes", multipathd will disable queueing when the +# # last path to a device has been deleted. +# # values : yes|no +# # default : no +# # +# flush_on_last_del yes +# # # # # name : user_friendly_names # # scope : multipath @@ -284,6 +293,16 @@ # #no_path_retry queue # # # +# # name : flush_on_last_del +# # scope : multipathd +# # desc : If set to "yes", multipathd will disable queueing +# # when the last path to a device has been deleted. +# # values : yes|no +# # default : no +# # +# flush_on_last_del yes +# +# # # # name : rr_min_io # # scope : multipath # # desc : the number of IO to route to a path before switching @@ -422,6 +441,16 @@ # rr_min_io 100 # # # +# # name : flush_on_last_del +# # scope : multipathd +# # desc : If set to "yes", multipathd will disable queueing +# # when the last path to a device has been deleted. +# # values : yes|no +# # default : no +# # +# flush_on_last_del yes +# +# # # # name : product_blacklist # # scope : multipath & multipathd # # desc : product strings to blacklist for this vendor --- multipath-tools/multipath.conf.synthetic 2008/08/25 20:59:05 1.11.2.4 +++ multipath-tools/multipath.conf.synthetic 2008/09/04 20:09:48 1.11.2.5 @@ -16,6 +16,7 @@ # failback immediate # no_path_retry fail # user_friendly_names no +# flush_on_last_del no # mode 0666 # uid 0 # gid 0 --- multipath-tools/libmultipath/config.c 2008/08/25 20:59:06 1.19.2.6 +++ multipath-tools/libmultipath/config.c 2008/09/04 20:09:48 1.19.2.7 @@ -413,6 +413,7 @@ conf->minio = 1000; conf->max_fds = 0; conf->attribute_flags = 0; + conf->flush_on_last_del = 0; /* * read the config file --- multipath-tools/libmultipath/config.h 2008/08/25 20:59:06 1.18.2.5 +++ multipath-tools/libmultipath/config.h 2008/09/04 20:09:48 1.18.2.6 @@ -29,6 +29,7 @@ int no_path_retry; int minio; int pg_timeout; + int flush_on_last_del; struct checker * checker; char * bl_product; }; @@ -46,6 +47,7 @@ int minio; int pg_timeout; int attribute_flags; + int flush_on_last_del; uid_t uid; gid_t gid; mode_t mode; @@ -72,6 +74,7 @@ int max_fds; int force_reload; int attribute_flags; + int flush_on_last_del; uid_t uid; gid_t gid; mode_t mode; --- multipath-tools/libmultipath/dict.c 2008/08/29 21:30:34 1.17.2.6 +++ multipath-tools/libmultipath/dict.c 2008/09/04 20:09:48 1.17.2.7 @@ -297,6 +297,26 @@ } static int +def_flush_on_last_del_handler(vector strvec) +{ + char * buff; + + buff = set_value(strvec); + if (!buff) + return 1; + + if (!strncmp(buff, "no", 2) || !strncmp(buff, "0", 1)) + conf->flush_on_last_del = FLUSH_DISABLED; + else if (!strncmp(buff, "yes", 2) || !strncmp(buff, "1", 1)) + conf->flush_on_last_del = FLUSH_ENABLED; + else + conf->flush_on_last_del = FLUSH_UNDEF; + + free(buff); + return 0; +} + +static int def_pg_timeout_handler(vector strvec) { int pg_timeout; @@ -791,6 +811,30 @@ } static int +hw_flush_on_last_del_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 (!strncmp(buff, "no", 2) || !strncmp(buff, "0", 1)) + hwe->flush_on_last_del = FLUSH_DISABLED; + else if (!strncmp(buff, "yes", 2) || !strncmp(buff, "1", 1)) + hwe->flush_on_last_del = FLUSH_ENABLED; + else + hwe->flush_on_last_del = FLUSH_UNDEF; + + free(buff); + return 0; +} + +static int hw_pg_timeout_handler(vector strvec) { int pg_timeout; @@ -1013,6 +1057,30 @@ } static int +mp_flush_on_last_del_handler(vector strvec) +{ + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); + char * buff; + + if (!mpe) + return 1; + + buff = set_value(strvec); + if (!buff) + return 1; + + if (!strncmp(buff, "no", 2) || !strncmp(buff, "0", 1)) + mpe->flush_on_last_del = FLUSH_DISABLED; + else if (!strncmp(buff, "yes", 2) || !strncmp(buff, "1", 1)) + mpe->flush_on_last_del = FLUSH_ENABLED; + else + mpe->flush_on_last_del = FLUSH_UNDEF; + + free(buff); + return 0; +} + +static int mp_mode_handler(vector strvec) { mode_t mode; @@ -1272,6 +1340,20 @@ } static int +snprint_mp_flush_on_last_del (char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + switch (mpe->flush_on_last_del) { + case FLUSH_DISABLED: + return snprintf(buff, len, "no"); + case FLUSH_ENABLED: + return snprintf(buff, len, "yes"); + } + return 0; +} + +static int snprint_mp_pg_timeout (char * buff, int len, void * data) { struct mpentry * mpe = (struct mpentry *)data; @@ -1489,6 +1571,20 @@ } static int +snprint_hw_flush_on_last_del (char * buff, int len, void * data) +{ + struct hwentry * hwe = (struct hwentry *)data; + + switch (hwe->flush_on_last_del) { + case FLUSH_DISABLED: + return snprintf(buff, len, "no"); + case FLUSH_ENABLED: + return snprintf(buff, len, "yes"); + } + return 0; +} + +static int snprint_hw_pg_timeout (char * buff, int len, void * data) { struct hwentry * hwe = (struct hwentry *)data; @@ -1716,6 +1812,18 @@ } static int +snprint_def_flush_on_last_del (char * buff, int len, void * data) +{ + switch (conf->flush_on_last_del) { + case FLUSH_DISABLED: + return snprintf(buff, len, "no"); + case FLUSH_ENABLED: + return snprintf(buff, len, "yes"); + } + return 0; +} + +static int snprint_def_pg_timeout (char * buff, int len, void * data) { if (conf->pg_timeout == DEFAULT_PGTIMEOUT) @@ -1798,6 +1906,7 @@ install_keyword("max_fds", &max_fds_handler, &snprint_max_fds); install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight); install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); + install_keyword("flush_on_last_del", &def_flush_on_last_del_handler, &snprint_def_flush_on_last_del); install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names); install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file); @@ -1856,6 +1965,7 @@ install_keyword("rr_weight", &hw_weight_handler, &snprint_hw_rr_weight); install_keyword("no_path_retry", &hw_no_path_retry_handler, &snprint_hw_no_path_retry); install_keyword("rr_min_io", &hw_minio_handler, &snprint_hw_rr_min_io); + install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del); install_keyword("pg_timeout", &hw_pg_timeout_handler, &snprint_hw_pg_timeout); install_sublevel_end(); @@ -1870,6 +1980,7 @@ install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight); install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry); install_keyword("rr_min_io", &mp_minio_handler, &snprint_mp_rr_min_io); + install_keyword("flush_on_last_del", &mp_flush_on_last_del_handler, &snprint_mp_flush_on_last_del); install_keyword("pg_timeout", &mp_pg_timeout_handler, &snprint_mp_pg_timeout); install_keyword("mode", &mp_mode_handler, &snprint_mp_mode); install_keyword("uid", &mp_uid_handler, &snprint_mp_uid); --- multipath-tools/libmultipath/propsel.c 2008/08/25 20:59:06 1.11.2.1 +++ multipath-tools/libmultipath/propsel.c 2008/09/04 20:09:48 1.11.2.2 @@ -279,6 +279,10 @@ extern int select_no_path_retry(struct multipath *mp) { + if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) { + condlog(0, "flush_on_last_del in progress"); + mp->no_path_retry = NO_PATH_RETRY_FAIL; + } if (mp->mpe && mp->mpe->no_path_retry != NO_PATH_RETRY_UNDEF) { mp->no_path_retry = mp->mpe->no_path_retry; condlog(3, "%s: no_path_retry = %i (multipath setting)", @@ -385,6 +389,34 @@ } extern int +select_flush_on_last_del(struct multipath *mp) +{ + if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) + return 0; + if (mp->mpe && mp->mpe->flush_on_last_del != FLUSH_UNDEF) { + mp->flush_on_last_del = mp->mpe->flush_on_last_del; + condlog(3, "flush_on_last_del = %i (multipath setting)", + mp->flush_on_last_del); + return 0; + } + if (mp->hwe && mp->hwe->flush_on_last_del != FLUSH_UNDEF) { + mp->flush_on_last_del = mp->hwe->flush_on_last_del; + condlog(3, "flush_on_last_del = %i (controler setting)", + mp->flush_on_last_del); + return 0; + } + if (conf->flush_on_last_del != FLUSH_UNDEF) { + mp->flush_on_last_del = conf->flush_on_last_del; + condlog(3, "flush_on_last_del = %i (config file default)", + mp->flush_on_last_del); + return 0; + } + mp->flush_on_last_del = FLUSH_UNDEF; + condlog(3, "flush_on_last_del = DISABLED (internal default)"); + return 0; +} + +extern int select_pg_timeout(struct multipath *mp) { if (mp->mpe && mp->mpe->pg_timeout != PGTIMEOUT_UNDEF) { --- multipath-tools/libmultipath/propsel.h 2008/08/25 20:59:06 1.5.2.1 +++ multipath-tools/libmultipath/propsel.h 2008/09/04 20:09:48 1.5.2.2 @@ -14,3 +14,4 @@ int select_mode(struct multipath *mp); int select_uid(struct multipath *mp); int select_gid(struct multipath *mp); +int select_flush_on_last_del(struct multipath *mp); --- multipath-tools/libmultipath/structs.h 2008/08/29 21:30:34 1.18.2.4 +++ multipath-tools/libmultipath/structs.h 2008/09/04 20:09:48 1.18.2.5 @@ -71,6 +71,13 @@ ATTR_MODE, }; +enum flush_states { + FLUSH_UNDEF, + FLUSH_DISABLED, + FLUSH_ENABLED, + FLUSH_IN_PROGRESS, +}; + struct scsi_idlun { int dev_id; int host_unique_id; @@ -145,6 +152,7 @@ int minio; int pg_timeout; int attribute_flags; + int flush_on_last_del; uid_t uid; gid_t gid; mode_t mode; --- multipath-tools/libmultipath/structs_vec.c 2008/08/25 20:59:06 1.1.2.2 +++ multipath-tools/libmultipath/structs_vec.c 2008/09/04 20:09:48 1.1.2.3 @@ -290,6 +290,7 @@ select_pgfailback(mpp); set_no_path_retry(mpp); select_pg_timeout(mpp); + select_flush_on_last_del(mpp); return 0; out: --- multipath-tools/multipathd/cli.c 2007/01/10 20:08:09 1.5.2.1 +++ multipath-tools/multipathd/cli.c 2008/09/04 20:09:48 1.5.2.2 @@ -129,6 +129,8 @@ r += add_key(keys, "resume", RESUME, 0); r += add_key(keys, "reinstate", REINSTATE, 0); r += add_key(keys, "fail", FAIL, 0); + r += add_key(keys, "disablequeueing", DISABLEQ, 0); + r += add_key(keys, "restorequeueing", RESTOREQ, 0); r += add_key(keys, "paths", PATHS, 0); r += add_key(keys, "maps", MAPS, 0); r += add_key(keys, "multipaths", MAPS, 0); --- multipath-tools/multipathd/cli.h 2007/01/10 20:08:09 1.5.2.1 +++ multipath-tools/multipathd/cli.h 2008/09/04 20:09:48 1.5.2.2 @@ -7,6 +7,8 @@ __RESUME, __REINSTATE, __FAIL, + __DISABLEQ, + __RESTOREQ, __PATHS, __MAPS, __PATH, @@ -29,6 +31,8 @@ #define RESUME (1 << __RESUME) #define REINSTATE (1 << __REINSTATE) #define FAIL (1 << __FAIL) +#define DISABLEQ (1 << __DISABLEQ) +#define RESTOREQ (1 << __RESTOREQ) #define PATHS (1 << __PATHS) #define MAPS (1 << __MAPS) #define PATH (1 << __PATH) --- multipath-tools/multipathd/cli_handlers.c 2007/01/10 20:08:09 1.6.2.1 +++ multipath-tools/multipathd/cli_handlers.c 2008/09/04 20:09:48 1.6.2.2 @@ -336,6 +336,48 @@ } int +cli_restore_queueing(void *v, char **reply, int *len, void *data) +{ + struct vectors * vecs = (struct vectors *)data; + char * mapname = get_keyparam(v, MAP); + struct multipath *mpp; + int minor; + + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); + else + mpp = find_mp_by_alias(vecs->mpvec, mapname); + + if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF && + mpp->no_path_retry != NO_PATH_RETRY_FAIL) { + dm_queue_if_no_path(mpp->alias, 1); + if (mpp->nr_active > 0) + mpp->retry_tick = 0; + else + mpp->retry_tick = mpp->no_path_retry * conf->checkint; + } + return 0; +} + +int +cli_disable_queueing(void *v, char **reply, int *len, void *data) +{ + struct vectors * vecs = (struct vectors *)data; + char * mapname = get_keyparam(v, MAP); + struct multipath *mpp; + int minor; + + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); + else + mpp = find_mp_by_alias(vecs->mpvec, mapname); + + mpp->retry_tick = 0; + dm_queue_if_no_path(mpp->alias, 0); + return 0; +} + +int cli_switch_group(void * v, char ** reply, int * len, void * data) { char * mapname = get_keyparam(v, MAP); --- multipath-tools/multipathd/cli_handlers.h 2007/01/10 20:08:09 1.3.2.1 +++ multipath-tools/multipathd/cli_handlers.h 2008/09/04 20:09:48 1.3.2.2 @@ -13,6 +13,8 @@ int cli_del_map (void * v, char ** reply, int * len, void * data); int cli_switch_group(void * v, char ** reply, int * len, void * data); int cli_reconfigure(void * v, char ** reply, int * len, void * data); +int cli_disable_queueing(void * v, char ** reply, int * len, void * data); +int cli_restore_queueing(void * v, char ** reply, int * len, void * data); int cli_suspend(void * v, char ** reply, int * len, void * data); int cli_resume(void * v, char ** reply, int * len, void * data); int cli_reinstate(void * v, char ** reply, int * len, void * data); --- multipath-tools/multipathd/main.c 2008/08/29 21:30:34 1.69.2.9 +++ multipath-tools/multipathd/main.c 2008/09/04 20:09:48 1.69.2.10 @@ -406,6 +406,7 @@ return 1; /* leave path added to pathvec */ verify_paths(mpp, vecs, NULL); + mpp->flush_on_last_del = FLUSH_UNDEF; mpp->action = ACT_RELOAD; } else { @@ -511,6 +512,13 @@ * flush_map will fail if the device is open */ strncpy(alias, mpp->alias, WWID_SIZE); + if (mpp->flush_on_last_del == FLUSH_ENABLED) { + condlog(2, "%s Last path deleted, disabling queueing", mpp->alias); + mpp->retry_tick = 0; + mpp->no_path_retry = NO_PATH_RETRY_FAIL; + mpp->flush_on_last_del == FLUSH_IN_PROGRESS; + dm_queue_if_no_path(mpp->alias, 0); + } if (flush_map(mpp, vecs)) rm_path = 0; else @@ -563,6 +571,13 @@ * flush_map will fail if the device is open */ strncpy(alias, mpp->alias, WWID_SIZE); + if (mpp->flush_on_last_del == FLUSH_ENABLED) { + condlog(2, "%s Last path deleted, disabling queueing", mpp->alias); + mpp->retry_tick = 0; + mpp->no_path_retry = NO_PATH_RETRY_FAIL; + mpp->flush_on_last_del == FLUSH_IN_PROGRESS; + dm_queue_if_no_path(mpp->alias, 0); + } if (flush_map(mpp, vecs)) rm_path = 0; else @@ -746,6 +761,8 @@ add_handler(RESUME+MAP, cli_resume); add_handler(REINSTATE+PATH, cli_reinstate); add_handler(FAIL+PATH, cli_fail); + add_handler(DISABLEQ+MAP, cli_disable_queueing); + add_handler(RESTOREQ+MAP, cli_restore_queueing); uxsock_listen(&uxsock_trigger, ap); -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel