<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from rtf -->
<style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<font face="Calibri" size="2"><span style="font-size:11pt;">
<div>This patch adds three configuration parameters, "san_path_err_threshold",</div>
<div>"san_path_err_recovery_time" and "san_path_err_forget_rate".</div>
<div>multipathd will watch paths and check how many times a path has been failed due</div>
<div>to errors.If the number of failures on a particular path is greater then the</div>
<div>san_path_err_threshold then the path will not  reinstante till</div>
<div>san_path_err_recovery_time.These path failures should occur within a</div>
<div>san_path_err_forget_rate checks, if not we will consider the path is good enough</div>
<div>to reinstantate.If it is the only available path, it will immediately be</div>
<div>reintegrated.</div>
<div> </div>
<div>This helps us to place the path in failed state if we hit lot of errors on a particular path</div>
<div>due to network /target issues and allow the admin to rectify the errors on a path.</div>
<div> </div>
<div>Signed-off-by: M Muneendra Kumar <mmandala@brocade.com></div>
<div> </div>
<div> </div>
<div>diff --git a/libmultipath/config.c b/libmultipath/config.c</div>
<div>index 15ddbd8..5837dc6 100644</div>
<div>--- a/libmultipath/config.c</div>
<div>+++ b/libmultipath/config.c</div>
<div>@@ -348,6 +348,9 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)</div>
<div>         merge_num(delay_wait_checks);</div>
<div>         merge_num(skip_kpartx);</div>
<div>         merge_num(max_sectors_kb);</div>
<div>+       merge_num(san_path_err_threshold);</div>
<div>+       merge_num(san_path_err_forget_rate);</div>
<div>+       merge_num(san_path_err_recovery_time);</div>
<div> </div>
<div>         /*</div>
<div>          * Make sure features is consistent with</div>
<div>@@ -621,6 +624,9 @@ load_config (char * file)</div>
<div>         conf->disable_changed_wwids = DEFAULT_DISABLE_CHANGED_WWIDS;</div>
<div>         conf->remove_retries = 0;</div>
<div>         conf->max_sectors_kb = DEFAULT_MAX_SECTORS_KB;</div>
<div>+       conf->san_path_err_threshold = DEFAULT_ERR_CHECKS;</div>
<div>+       conf->san_path_err_forget_rate = DEFAULT_ERR_CHECKS;</div>
<div>+       conf->san_path_err_recovery_time = DEFAULT_ERR_CHECKS;</div>
<div> </div>
<div>         /*</div>
<div>          * preload default hwtable</div>
<div>diff --git a/libmultipath/config.h b/libmultipath/config.h</div>
<div>index 9670020..9e47894 100644</div>
<div>--- a/libmultipath/config.h</div>
<div>+++ b/libmultipath/config.h</div>
<div>@@ -65,6 +65,9 @@ struct hwentry {</div>
<div>         int deferred_remove;</div>
<div>         int delay_watch_checks;</div>
<div>         int delay_wait_checks;</div>
<div>+       int san_path_err_threshold;</div>
<div>+       int san_path_err_forget_rate;</div>
<div>+       int san_path_err_recovery_time;</div>
<div>         int skip_kpartx;</div>
<div>         int max_sectors_kb;</div>
<div>         char * bl_product;</div>
<div>@@ -93,6 +96,9 @@ struct mpentry {</div>
<div>         int deferred_remove;</div>
<div>         int delay_watch_checks;</div>
<div>         int delay_wait_checks;</div>
<div>+       int san_path_err_threshold;</div>
<div>+       int san_path_err_forget_rate;</div>
<div>+       int san_path_err_recovery_time;</div>
<div>         int skip_kpartx;</div>
<div>         int max_sectors_kb;</div>
<div>         uid_t uid;</div>
<div>@@ -138,6 +144,9 @@ struct config {</div>
<div>         int processed_main_config;</div>
<div>         int delay_watch_checks;</div>
<div>         int delay_wait_checks;</div>
<div>+       int san_path_err_threshold;</div>
<div>+       int san_path_err_forget_rate;</div>
<div>+       int san_path_err_recovery_time;</div>
<div>         int uxsock_timeout;</div>
<div>         int strict_timing;</div>
<div>         int retrigger_tries;</div>
<div>diff --git a/libmultipath/configure.c b/libmultipath/configure.c</div>
<div>index a0fcad9..5ad3007 100644</div>
<div>--- a/libmultipath/configure.c</div>
<div>+++ b/libmultipath/configure.c</div>
<div>@@ -294,6 +294,9 @@ int setup_map(struct multipath *mpp, char *params, int params_size)</div>
<div>         select_deferred_remove(conf, mpp);</div>
<div>         select_delay_watch_checks(conf, mpp);</div>
<div>         select_delay_wait_checks(conf, mpp);</div>
<div>+       select_san_path_err_threshold(conf, mpp);</div>
<div>+       select_san_path_err_forget_rate(conf, mpp);</div>
<div>+       select_san_path_err_recovery_time(conf, mpp);</div>
<div>         select_skip_kpartx(conf, mpp);</div>
<div>         select_max_sectors_kb(conf, mpp);</div>
<div> </div>
<div>diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h</div>
<div>index b9b0a37..3ef1579 100644</div>
<div>--- a/libmultipath/defaults.h</div>
<div>+++ b/libmultipath/defaults.h</div>
<div>@@ -23,7 +23,8 @@</div>
<div> #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON</div>
<div> #define DEFAULT_DETECT_PRIO    DETECT_PRIO_ON</div>
<div> #define DEFAULT_DEFERRED_REMOVE        DEFERRED_REMOVE_OFF</div>
<div>-#define DEFAULT_DELAY_CHECKS   DELAY_CHECKS_OFF</div>
<div>+#define DEFAULT_DELAY_CHECKS   NU_NO</div>
<div>+#define DEFAULT_ERR_CHECKS     NU_NO</div>
<div> #define DEFAULT_UEVENT_STACKSIZE 256</div>
<div> #define DEFAULT_RETRIGGER_DELAY        10</div>
<div> #define DEFAULT_RETRIGGER_TRIES        3</div>
<div>diff --git a/libmultipath/dict.c b/libmultipath/dict.c</div>
<div>index dc21846..ae94c88 100644</div>
<div>--- a/libmultipath/dict.c</div>
<div>+++ b/libmultipath/dict.c</div>
<div>@@ -1023,7 +1023,7 @@ declare_mp_handler(reservation_key, set_reservation_key)</div>
<div> declare_mp_snprint(reservation_key, print_reservation_key)</div>
<div> </div>
<div> static int</div>
<div>-set_delay_checks(vector strvec, void *ptr)</div>
<div>+set_off_int_undef(vector strvec, void *ptr)</div>
<div> {</div>
<div>         int *int_ptr = (int *)ptr;</div>
<div>         char * buff;</div>
<div>@@ -1033,47 +1033,69 @@ set_delay_checks(vector strvec, void *ptr)</div>
<div>                 return 1;</div>
<div> </div>
<div>         if (!strcmp(buff, "no") || !strcmp(buff, "0"))</div>
<div>-               *int_ptr = DELAY_CHECKS_OFF;</div>
<div>+               *int_ptr = NU_NO;</div>
<div>         else if ((*int_ptr = atoi(buff)) < 1)</div>
<div>-               *int_ptr = DELAY_CHECKS_UNDEF;</div>
<div>+               *int_ptr = NU_UNDEF;</div>
<div> </div>
<div>         FREE(buff);</div>
<div>         return 0;</div>
<div> }</div>
<div> </div>
<div> int</div>
<div>-print_delay_checks(char * buff, int len, void *ptr)</div>
<div>+print_off_int_undef(char * buff, int len, void *ptr)</div>
<div> {</div>
<div>         int *int_ptr = (int *)ptr;</div>
<div> </div>
<div>         switch(*int_ptr) {</div>
<div>-       case DELAY_CHECKS_UNDEF:</div>
<div>+       case NU_UNDEF:</div>
<div>                 return 0;</div>
<div>-       case DELAY_CHECKS_OFF:</div>
<div>-               return snprintf(buff, len, "\"off\"");</div>
<div>+       case NU_NO:</div>
<div>+               return snprintf(buff, len, "\"no\"");</div>
<div>         default:</div>
<div>                 return snprintf(buff, len, "%i", *int_ptr);</div>
<div>         }</div>
<div> }</div>
<div> </div>
<div>-declare_def_handler(delay_watch_checks, set_delay_checks)</div>
<div>-declare_def_snprint(delay_watch_checks, print_delay_checks)</div>
<div>-declare_ovr_handler(delay_watch_checks, set_delay_checks)</div>
<div>-declare_ovr_snprint(delay_watch_checks, print_delay_checks)</div>
<div>-declare_hw_handler(delay_watch_checks, set_delay_checks)</div>
<div>-declare_hw_snprint(delay_watch_checks, print_delay_checks)</div>
<div>-declare_mp_handler(delay_watch_checks, set_delay_checks)</div>
<div>-declare_mp_snprint(delay_watch_checks, print_delay_checks)</div>
<div>-</div>
<div>-declare_def_handler(delay_wait_checks, set_delay_checks)</div>
<div>-declare_def_snprint(delay_wait_checks, print_delay_checks)</div>
<div>-declare_ovr_handler(delay_wait_checks, set_delay_checks)</div>
<div>-declare_ovr_snprint(delay_wait_checks, print_delay_checks)</div>
<div>-declare_hw_handler(delay_wait_checks, set_delay_checks)</div>
<div>-declare_hw_snprint(delay_wait_checks, print_delay_checks)</div>
<div>-declare_mp_handler(delay_wait_checks, set_delay_checks)</div>
<div>-declare_mp_snprint(delay_wait_checks, print_delay_checks)</div>
<div>-</div>
<div>+declare_def_handler(delay_watch_checks, set_off_int_undef)</div>
<div>+declare_def_snprint(delay_watch_checks, print_off_int_undef)</div>
<div>+declare_ovr_handler(delay_watch_checks, set_off_int_undef)</div>
<div>+declare_ovr_snprint(delay_watch_checks, print_off_int_undef)</div>
<div>+declare_hw_handler(delay_watch_checks, set_off_int_undef)</div>
<div>+declare_hw_snprint(delay_watch_checks, print_off_int_undef)</div>
<div>+declare_mp_handler(delay_watch_checks, set_off_int_undef)</div>
<div>+declare_mp_snprint(delay_watch_checks, print_off_int_undef)</div>
<div>+declare_def_handler(delay_wait_checks, set_off_int_undef)</div>
<div>+declare_def_snprint(delay_wait_checks, print_off_int_undef)</div>
<div>+declare_ovr_handler(delay_wait_checks, set_off_int_undef)</div>
<div>+declare_ovr_snprint(delay_wait_checks, print_off_int_undef)</div>
<div>+declare_hw_handler(delay_wait_checks, set_off_int_undef)</div>
<div>+declare_hw_snprint(delay_wait_checks, print_off_int_undef)</div>
<div>+declare_mp_handler(delay_wait_checks, set_off_int_undef)</div>
<div>+declare_mp_snprint(delay_wait_checks, print_off_int_undef)</div>
<div>+declare_def_handler(san_path_err_threshold, set_off_int_undef)</div>
<div>+declare_def_snprint(san_path_err_threshold, print_off_int_undef)</div>
<div>+declare_ovr_handler(san_path_err_threshold, set_off_int_undef)</div>
<div>+declare_ovr_snprint(san_path_err_threshold, print_off_int_undef)</div>
<div>+declare_hw_handler(san_path_err_threshold, set_off_int_undef)</div>
<div>+declare_hw_snprint(san_path_err_threshold, print_off_int_undef)</div>
<div>+declare_mp_handler(san_path_err_threshold, set_off_int_undef)</div>
<div>+declare_mp_snprint(san_path_err_threshold, print_off_int_undef)</div>
<div>+declare_def_handler(san_path_err_forget_rate, set_off_int_undef)</div>
<div>+declare_def_snprint(san_path_err_forget_rate, print_off_int_undef)</div>
<div>+declare_ovr_handler(san_path_err_forget_rate, set_off_int_undef)</div>
<div>+declare_ovr_snprint(san_path_err_forget_rate, print_off_int_undef)</div>
<div>+declare_hw_handler(san_path_err_forget_rate, set_off_int_undef)</div>
<div>+declare_hw_snprint(san_path_err_forget_rate, print_off_int_undef)</div>
<div>+declare_mp_handler(san_path_err_forget_rate, set_off_int_undef)</div>
<div>+declare_mp_snprint(san_path_err_forget_rate, print_off_int_undef)</div>
<div>+declare_def_handler(san_path_err_recovery_time, set_off_int_undef)</div>
<div>+declare_def_snprint(san_path_err_recovery_time, print_off_int_undef)</div>
<div>+declare_ovr_handler(san_path_err_recovery_time, set_off_int_undef)</div>
<div>+declare_ovr_snprint(san_path_err_recovery_time, print_off_int_undef)</div>
<div>+declare_hw_handler(san_path_err_recovery_time, set_off_int_undef)</div>
<div>+declare_hw_snprint(san_path_err_recovery_time, print_off_int_undef)</div>
<div>+declare_mp_handler(san_path_err_recovery_time, set_off_int_undef)</div>
<div>+declare_mp_snprint(san_path_err_recovery_time, print_off_int_undef)</div>
<div> static int</div>
<div> def_uxsock_timeout_handler(struct config *conf, vector strvec)</div>
<div> {</div>
<div>@@ -1404,6 +1426,10 @@ init_keywords(vector keywords)</div>
<div>         install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);</div>
<div>         install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks);</div>
<div>         install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks);</div>
<div>+        install_keyword("san_path_err_threshold", &def_san_path_err_threshold_handler, &snprint_def_san_path_err_threshold);</div>
<div>+        install_keyword("san_path_err_forget_rate", &def_san_path_err_forget_rate_handler, &snprint_def_san_path_err_forget_rate);</div>
<div>+        install_keyword("san_path_err_recovery_time", &def_san_path_err_recovery_time_handler, &snprint_def_san_path_err_recovery_time);</div>
<div>+</div>
<div>         install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);</div>
<div>         install_keyword("uxsock_timeout", &def_uxsock_timeout_handler, &snprint_def_uxsock_timeout);</div>
<div>         install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries);</div>
<div>@@ -1486,6 +1512,9 @@ init_keywords(vector keywords)</div>
<div>         install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);</div>
<div>         install_keyword("delay_watch_checks", &hw_delay_watch_checks_handler, &snprint_hw_delay_watch_checks);</div>
<div>         install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks);</div>
<div>+        install_keyword("san_path_err_threshold", &hw_san_path_err_threshold_handler, &snprint_hw_san_path_err_threshold);</div>
<div>+        install_keyword("san_path_err_forget_rate", &hw_san_path_err_forget_rate_handler, &snprint_hw_san_path_err_forget_rate);</div>
<div>+        install_keyword("san_path_err_recovery_time", &hw_san_path_err_recovery_time_handler, &snprint_hw_san_path_err_recovery_time);</div>
<div>         install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx);</div>
<div>         install_keyword("max_sectors_kb", &hw_max_sectors_kb_handler, &snprint_hw_max_sectors_kb);</div>
<div>         install_sublevel_end();</div>
<div>@@ -1515,6 +1544,10 @@ init_keywords(vector keywords)</div>
<div>         install_keyword("deferred_remove", &ovr_deferred_remove_handler, &snprint_ovr_deferred_remove);</div>
<div>         install_keyword("delay_watch_checks", &ovr_delay_watch_checks_handler, &snprint_ovr_delay_watch_checks);</div>
<div>         install_keyword("delay_wait_checks", &ovr_delay_wait_checks_handler, &snprint_ovr_delay_wait_checks);</div>
<div>+        install_keyword("san_path_err_threshold", &ovr_san_path_err_threshold_handler, &snprint_ovr_san_path_err_threshold);</div>
<div>+        install_keyword("san_path_err_forget_rate", &ovr_san_path_err_forget_rate_handler, &snprint_ovr_san_path_err_forget_rate);</div>
<div>+        install_keyword("san_path_err_recovery_time", &ovr_san_path_err_recovery_time_handler, &snprint_ovr_san_path_err_recovery_time);</div>
<div>+</div>
<div>         install_keyword("skip_kpartx", &ovr_skip_kpartx_handler, &snprint_ovr_skip_kpartx);</div>
<div>         install_keyword("max_sectors_kb", &ovr_max_sectors_kb_handler, &snprint_ovr_max_sectors_kb);</div>
<div> </div>
<div>@@ -1543,6 +1576,9 @@ init_keywords(vector keywords)</div>
<div>         install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);</div>
<div>         install_keyword("delay_watch_checks", &mp_delay_watch_checks_handler, &snprint_mp_delay_watch_checks);</div>
<div>         install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks);</div>
<div>+       install_keyword("san_path_err_threshold", &mp_san_path_err_threshold_handler, &snprint_mp_san_path_err_threshold);</div>
<div>+       install_keyword("san_path_err_forget_rate", &mp_san_path_err_forget_rate_handler, &snprint_mp_san_path_err_forget_rate);</div>
<div>+       install_keyword("san_path_err_recovery_time", &mp_san_path_err_recovery_time_handler, &snprint_mp_san_path_err_recovery_time);</div>
<div>         install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx);</div>
<div>         install_keyword("max_sectors_kb", &mp_max_sectors_kb_handler, &snprint_mp_max_sectors_kb);</div>
<div>         install_sublevel_end();</div>
<div>diff --git a/libmultipath/dict.h b/libmultipath/dict.h</div>
<div>index 4cd03c5..2d6097d 100644</div>
<div>--- a/libmultipath/dict.h</div>
<div>+++ b/libmultipath/dict.h</div>
<div>@@ -14,6 +14,5 @@ int print_no_path_retry(char * buff, int len, void *ptr);</div>
<div> int print_fast_io_fail(char * buff, int len, void *ptr);</div>
<div> int print_dev_loss(char * buff, int len, void *ptr);</div>
<div> int print_reservation_key(char * buff, int len, void * ptr);</div>
<div>-int print_delay_checks(char * buff, int len, void *ptr);</div>
<div>-</div>
<div>+int print_off_int_undef(char * buff, int len, void *ptr);</div>
<div> #endif /* _DICT_H */</div>
<div>diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c</div>
<div>index c0bc616..e4afef7 100644</div>
<div>--- a/libmultipath/propsel.c</div>
<div>+++ b/libmultipath/propsel.c</div>
<div>@@ -623,7 +623,7 @@ int select_delay_watch_checks(struct config *conf, struct multipath *mp)</div>
<div>         mp_set_conf(delay_watch_checks);</div>
<div>         mp_set_default(delay_watch_checks, DEFAULT_DELAY_CHECKS);</div>
<div> out:</div>
<div>-       print_delay_checks(buff, 12, &mp->delay_watch_checks);</div>
<div>+       print_off_int_undef(buff, 12, &mp->delay_watch_checks);</div>
<div>         condlog(3, "%s: delay_watch_checks = %s %s", mp->alias, buff, origin);</div>
<div>         return 0;</div>
<div> }</div>
<div>@@ -638,12 +638,56 @@ int select_delay_wait_checks(struct config *conf, struct multipath *mp)</div>
<div>         mp_set_conf(delay_wait_checks);</div>
<div>         mp_set_default(delay_wait_checks, DEFAULT_DELAY_CHECKS);</div>
<div> out:</div>
<div>-       print_delay_checks(buff, 12, &mp->delay_wait_checks);</div>
<div>+       print_off_int_undef(buff, 12, &mp->delay_wait_checks);</div>
<div>         condlog(3, "%s: delay_wait_checks = %s %s", mp->alias, buff, origin);</div>
<div>         return 0;</div>
<div> </div>
<div> }</div>
<div>+int select_san_path_err_threshold(struct config *conf, struct multipath *mp)</div>
<div>+{</div>
<div>+        char *origin, buff[12];</div>
<div>+</div>
<div>+        mp_set_mpe(san_path_err_threshold);</div>
<div>+        mp_set_ovr(san_path_err_threshold);</div>
<div>+        mp_set_hwe(san_path_err_threshold);</div>
<div>+        mp_set_conf(san_path_err_threshold);</div>
<div>+        mp_set_default(san_path_err_threshold, DEFAULT_ERR_CHECKS);</div>
<div>+out:</div>
<div>+        print_off_int_undef(buff, 12, &mp->san_path_err_threshold);</div>
<div>+        condlog(3, "%s: san_path_err_threshold = %s %s", mp->alias, buff, origin);</div>
<div>+        return 0;</div>
<div>+}</div>
<div>+</div>
<div>+int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp)</div>
<div>+{</div>
<div>+        char *origin, buff[12];</div>
<div>+</div>
<div>+        mp_set_mpe(san_path_err_forget_rate);</div>
<div>+        mp_set_ovr(san_path_err_forget_rate);</div>
<div>+        mp_set_hwe(san_path_err_forget_rate);</div>
<div>+        mp_set_conf(san_path_err_forget_rate);</div>
<div>+        mp_set_default(san_path_err_forget_rate, DEFAULT_ERR_CHECKS);</div>
<div>+out:</div>
<div>+        print_off_int_undef(buff, 12, &mp->san_path_err_forget_rate);</div>
<div>+        condlog(3, "%s: san_path_err_forget_rate = %s %s", mp->alias, buff, origin);</div>
<div>+        return 0;</div>
<div>+</div>
<div>+}</div>
<div>+int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp)</div>
<div>+{</div>
<div>+        char *origin, buff[12];</div>
<div> </div>
<div>+        mp_set_mpe(san_path_err_recovery_time);</div>
<div>+        mp_set_ovr(san_path_err_recovery_time);</div>
<div>+        mp_set_hwe(san_path_err_recovery_time);</div>
<div>+        mp_set_conf(san_path_err_recovery_time);</div>
<div>+        mp_set_default(san_path_err_recovery_time, DEFAULT_ERR_CHECKS);</div>
<div>+out:</div>
<div>+        print_off_int_undef(buff, 12, &mp->san_path_err_recovery_time);</div>
<div>+        condlog(3, "%s: san_path_err_recovery_time = %s %s", mp->alias, buff, origin);</div>
<div>+        return 0;</div>
<div>+</div>
<div>+}</div>
<div> int select_skip_kpartx (struct config *conf, struct multipath * mp)</div>
<div> {</div>
<div>         char *origin;</div>
<div>diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h</div>
<div>index ad98fa5..e5b6f93 100644</div>
<div>--- a/libmultipath/propsel.h</div>
<div>+++ b/libmultipath/propsel.h</div>
<div>@@ -24,3 +24,6 @@ int select_delay_watch_checks (struct config *conf, struct multipath * mp);</div>
<div> int select_delay_wait_checks (struct config *conf, struct multipath * mp);</div>
<div> int select_skip_kpartx (struct config *conf, struct multipath * mp);</div>
<div> int select_max_sectors_kb (struct config *conf, struct multipath * mp);</div>
<div>+int select_san_path_err_forget_rate(struct config *conf, struct multipath *mp);</div>
<div>+int select_san_path_err_threshold(struct config *conf, struct multipath *mp);</div>
<div>+int select_san_path_err_recovery_time(struct config *conf, struct multipath *mp);</div>
<div>diff --git a/libmultipath/structs.h b/libmultipath/structs.h</div>
<div>index 396f69d..6edd927 100644</div>
<div>--- a/libmultipath/structs.h</div>
<div>+++ b/libmultipath/structs.h</div>
<div>@@ -152,9 +152,9 @@ enum scsi_protocol {</div>
<div>         SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */</div>
<div> };</div>
<div> </div>
<div>-enum delay_checks_states {</div>
<div>-       DELAY_CHECKS_OFF = -1,</div>
<div>-       DELAY_CHECKS_UNDEF = 0,</div>
<div>+enum no_undef_states {</div>
<div>+       NU_NO = -1,</div>
<div>+       NU_UNDEF = 0,</div>
<div> };</div>
<div> </div>
<div> enum initialized_states {</div>
<div>@@ -223,7 +223,10 @@ struct path {</div>
<div>         int initialized;</div>
<div>         int retriggers;</div>
<div>         int wwid_changed;</div>
<div>-</div>
<div>+       unsigned int path_failures;</div>
<div>+       time_t dis_reinstate_time;</div>
<div>+       int disable_reinstate;</div>
<div>+       int san_path_err_forget_rate;</div>
<div>         /* configlet pointers */</div>
<div>         struct hwentry * hwe;</div>
<div> };</div>
<div>@@ -255,6 +258,9 @@ struct multipath {</div>
<div>         int deferred_remove;</div>
<div>         int delay_watch_checks;</div>
<div>         int delay_wait_checks;</div>
<div>+       int san_path_err_threshold;</div>
<div>+       int san_path_err_forget_rate;</div>
<div>+       int san_path_err_recovery_time;</div>
<div>         int skip_kpartx;</div>
<div>         int max_sectors_kb;</div>
<div>         unsigned int dev_loss;</div>
<div>diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5</div>
<div>index 36589f5..3c564ad 100644</div>
<div>--- a/multipath/multipath.conf.5</div>
<div>+++ b/multipath/multipath.conf.5</div>
<div>@@ -751,6 +751,45 @@ The default is: \fB/etc/multipath/conf.d/\fR</div>
<div> .</div>
<div> .</div>
<div> .TP</div>
<div>+.B san_path_err_threshold</div>
<div>+If set to a value greater than 0, multipathd will watch paths and check how many</div>
<div>+times a path has been failed due to errors.If the number of failures on a particular</div>
<div>+path is greater then the san_path_err_threshold then the path will not  reinstante</div>
<div>+till san_path_err_recovery_time.These path failures should occur within a </div>
<div>+san_path_err_forget_rate checks, if not we will consider the path is good enough</div>
<div>+to reinstantate.</div>
<div>+.RS</div>
<div>+.TP</div>
<div>+The default is: \fBno\fR</div>
<div>+.RE</div>
<div>+.</div>
<div>+.</div>
<div>+.TP</div>
<div>+.B san_path_err_forget_rate</div>
<div>+If set to a value greater than 0, multipathd will check whether the path failures</div>
<div>+has exceeded  the san_path_err_threshold within this many checks i.e </div>
<div>+san_path_err_forget_rate . If so we will not reinstante the path till</div>
<div>+san_path_err_recovery_time.</div>
<div>+.RS</div>
<div>+.TP</div>
<div>+The default is: \fBno\fR</div>
<div>+.RE</div>
<div>+.</div>
<div>+.</div>
<div>+.TP</div>
<div>+.B san_path_err_recovery_time</div>
<div>+If set to a value greater than 0, multipathd will make sure that when path failures</div>
<div>+has exceeded the san_path_err_threshold within san_path_err_forget_rate then the path</div>
<div>+will be placed in failed state for san_path_err_recovery_time duration.Once san_path_err_recovery_time</div>
<div>+has timeout  we will reinstante the failed path .</div>
<div>+san_path_err_recovery_time value should be in secs.</div>
<div>+.RS</div>
<div>+.TP</div>
<div>+The default is: \fBno\fR</div>
<div>+.RE</div>
<div>+.</div>
<div>+.</div>
<div>+.TP</div>
<div> .B delay_watch_checks</div>
<div> If set to a value greater than 0, multipathd will watch paths that have</div>
<div> recently become valid for this many checks. If they fail again while they are</div>
<div>@@ -1015,6 +1054,12 @@ are taken from the \fIdefaults\fR or \fIdevices\fR section:</div>
<div> .TP</div>
<div> .B deferred_remove</div>
<div> .TP</div>
<div>+.B san_path_err_threshold</div>
<div>+.TP</div>
<div>+.B san_path_err_forget_rate</div>
<div>+.TP</div>
<div>+.B san_path_err_recovery_time</div>
<div>+.TP</div>
<div> .B delay_watch_checks</div>
<div> .TP</div>
<div> .B delay_wait_checks</div>
<div>@@ -1128,6 +1173,12 @@ section:</div>
<div> .TP</div>
<div> .B deferred_remove</div>
<div> .TP</div>
<div>+.B san_path_err_threshold</div>
<div>+.TP</div>
<div>+.B san_path_err_forget_rate</div>
<div>+.TP</div>
<div>+.B san_path_err_recovery_time</div>
<div>+.TP</div>
<div> .B delay_watch_checks</div>
<div> .TP</div>
<div> .B delay_wait_checks</div>
<div>@@ -1192,6 +1243,12 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections:</div>
<div> .TP</div>
<div> .B deferred_remove</div>
<div> .TP</div>
<div>+.B san_path_err_threshold</div>
<div>+.TP</div>
<div>+.B san_path_err_forget_rate</div>
<div>+.TP</div>
<div>+.B san_path_err_recovery_time</div>
<div>+.TP</div>
<div> .B delay_watch_checks</div>
<div> .TP</div>
<div> .B delay_wait_checks</div>
<div>diff --git a/multipathd/main.c b/multipathd/main.c</div>
<div>index adc3258..4a1a7ef 100644</div>
<div>--- a/multipathd/main.c</div>
<div>+++ b/multipathd/main.c</div>
<div>@@ -1487,6 +1487,83 @@ void repair_path(struct path * pp)</div>
<div>         LOG_MSG(1, checker_message(&pp->checker));</div>
<div> }</div>
<div> </div>
<div>+static int check_path_reinstate_state(struct path * pp) {</div>
<div>+       struct timespec curr_time;</div>
<div>+       if (!((pp->mpp->san_path_err_threshold > 0) &&</div>
<div>+                               (pp->mpp->san_path_err_forget_rate > 0) &&</div>
<div>+                               (pp->mpp->san_path_err_recovery_time >0))) {</div>
<div>+               return 0;</div>
<div>+       }</div>
<div>+       </div>
<div>+       if (pp->disable_reinstate) {</div>
<div>+               /* If we don't know how much time has passed, automatically</div>
<div>+                * reinstate the path, just to be safe. Also, if there are</div>
<div>+                * no other usable paths, reinstate the path </div>
<div>+                */</div>
<div>+               if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0 ||</div>
<div>+                               pp->mpp->nr_active == 0) {</div>
<div>+                       condlog(2, "%s : reinstating path early", pp->dev);</div>
<div>+                       goto reinstate_path;</div>
<div>+               }</div>
<div>+               if ((curr_time.tv_sec - pp->dis_reinstate_time ) > pp->mpp->san_path_err_recovery_time) {</div>
<div>+                       condlog(2,"%s : reinstate the path after err recovery time", pp->dev);</div>
<div>+                       goto reinstate_path;</div>
<div>+               }</div>
<div>+               return 1;</div>
<div>+       }</div>
<div>+       /* forget errors on a working path */</div>
<div>+       if ((pp->state == PATH_UP || pp->state == PATH_GHOST) &&</div>
<div>+                       pp->path_failures > 0) {</div>
<div>+               if (pp->san_path_err_forget_rate > 0){</div>
<div>+                       pp->san_path_err_forget_rate--;</div>
<div>+               } else {</div>
<div>+                       /* for every san_path_err_forget_rate number of </div>
<div>+                        * successful path checks decrement path_failures by 1</div>
<div>+                        */</div>
<div>+                       pp->path_failures--;</div>
<div>+                       pp->san_path_err_forget_rate = pp->mpp->san_path_err_forget_rate;</div>
<div>+               }</div>
<div>+               return 0;</div>
<div>+       }</div>
<div>+</div>
<div>+       /* If the path isn't recovering from a failed state, do nothing */</div>
<div>+       if (pp->state != PATH_DOWN && pp->state != PATH_SHAKY &&</div>
<div>+                       pp->state != PATH_TIMEOUT)</div>
<div>+               return 0;</div>
<div>+</div>
<div>+       if (pp->path_failures == 0)</div>
<div>+               pp->san_path_err_forget_rate = pp->mpp->san_path_err_forget_rate;</div>
<div>+</div>
<div>+       pp->path_failures++;</div>
<div>+</div>
<div>+       /* if we don't know the currently time, we don't know how long to</div>
<div>+        * delay the path, so there's no point in checking if we should </div>
<div>+        */</div>
<div>+</div>
<div>+       if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)</div>
<div>+               return 0;</div>
<div>+       /* when path failures has exceeded the san_path_err_threshold</div>
<div>+        * place the path in delayed state till san_path_err_recovery_time</div>
<div>+        * so that the cutomer can rectify the issue within this time. After</div>
<div>+        * the completion of san_path_err_recovery_time it should</div>
<div>+        * automatically reinstate the path </div>
<div>+        */</div>
<div>+       if (pp->path_failures > pp->mpp->san_path_err_threshold) {</div>
<div>+               condlog(2, "%s : hit error threshold. Delaying path reinstatement", pp->dev);</div>
<div>+               pp->dis_reinstate_time = curr_time.tv_sec;</div>
<div>+               pp->disable_reinstate = 1;</div>
<div>+               return 1;</div>
<div>+       } else {</div>
<div>+               return 0;</div>
<div>+       }</div>
<div>+</div>
<div>+reinstate_path:</div>
<div>+       pp->path_failures = 0;</div>
<div>+       pp->disable_reinstate = 0;</div>
<div>+       pp->san_path_err_forget_rate = 0;</div>
<div>+       return 0;</div>
<div>+}</div>
<div>+</div>
<div> /*</div>
<div>  * Returns '1' if the path has been checked, '-1' if it was blacklisted</div>
<div>  * and '0' otherwise</div>
<div>@@ -1601,6 +1678,12 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)</div>
<div>                 return 0;</div>
<div> </div>
<div>         if ((newstate == PATH_UP || newstate == PATH_GHOST) &&</div>
<div>+                       check_path_reinstate_state(pp)) {</div>
<div>+               pp->state = PATH_DELAYED;</div>
<div>+               return 1;</div>
<div>+       }</div>
<div>+</div>
<div>+       if ((newstate == PATH_UP || newstate == PATH_GHOST) &&</div>
<div>              pp->wait_checks > 0) {</div>
<div>                 if (pp->mpp->nr_active > 0) {</div>
<div>                         pp->state = PATH_DELAYED;</div>
<div>-- </div>
<div>1.8.3.1</div>
<div> </div>
</span></font>
</body>
</html>