[dm-devel] [PATCH 4/5] libmultipath: fix (max_)polling_interval setting logic

Benjamin Marzinski bmarzins at redhat.com
Tue Nov 19 22:31:08 UTC 2019


On Fri, Nov 15, 2019 at 02:41:52PM +0000, Martin Wilck wrote:
> From: Martin Wilck <mwilck at suse.com>
> 
> checkint should never be larger than max_checkint. The WATCHDOG_USEC
> setting should be honored on "reconfigure", too, not only on startup.
> Pathological values for checkint and integer overflows should be avoided.
> The logic should work reasonably well if both polling_interval and
> max_polling_interval, just one of them, or neither is set.
> 
Reviewed-by: Benjamin Marzinski <bmarzins at redhat.com>
> Signed-off-by: Martin Wilck <mwilck at suse.com>
> ---
>  libmultipath/config.c   | 40 +++++++++++++++++++++++++++++++++++++---
>  libmultipath/config.h   |  1 +
>  libmultipath/defaults.h |  3 +--
>  multipathd/main.c       | 26 ++++++--------------------
>  4 files changed, 45 insertions(+), 25 deletions(-)
> 
> diff --git a/libmultipath/config.c b/libmultipath/config.c
> index 49723add..0bf7bb40 100644
> --- a/libmultipath/config.c
> +++ b/libmultipath/config.c
> @@ -683,6 +683,27 @@ process_config_dir(struct config *conf, char *dir)
>  	pthread_cleanup_pop(1);
>  }
>  
> +static void set_max_checkint_from_watchdog(struct config *conf)
> +{
> +#ifdef USE_SYSTEMD
> +	char *envp = getenv("WATCHDOG_USEC");
> +	unsigned long checkint;
> +
> +	if (envp && sscanf(envp, "%lu", &checkint) == 1) {
> +		/* Value is in microseconds */
> +		checkint /= 1000000;
> +		if (checkint < 1 || checkint > UINT_MAX) {
> +			condlog(1, "invalid value for WatchdogSec: \"%s\"", envp);
> +			return;
> +		}
> +		if (conf->max_checkint == 0 || conf->max_checkint > checkint)
> +			conf->max_checkint = checkint;
> +		condlog(3, "enabling watchdog, interval %ld", checkint);
> +		conf->use_watchdog = true;
> +	}
> +#endif
> +}
> +
>  struct config *
>  load_config (char * file)
>  {
> @@ -703,7 +724,8 @@ load_config (char * file)
>  	conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
>  	conf->attribute_flags = 0;
>  	conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
> -	conf->checkint = DEFAULT_CHECKINT;
> +	conf->checkint = CHECKINT_UNDEF;
> +	conf->use_watchdog = false;
>  	conf->max_checkint = 0;
>  	conf->force_sync = DEFAULT_FORCE_SYNC;
>  	conf->partition_delim = (default_partition_delim != NULL ?
> @@ -754,8 +776,20 @@ load_config (char * file)
>  	/*
>  	 * fill the voids left in the config file
>  	 */
> -	if (conf->max_checkint == 0)
> -		conf->max_checkint = MAX_CHECKINT(conf->checkint);
> +	set_max_checkint_from_watchdog(conf);
> +	if (conf->max_checkint == 0) {
> +		if (conf->checkint == CHECKINT_UNDEF)
> +			conf->checkint = DEFAULT_CHECKINT;
> +		conf->max_checkint = (conf->checkint < UINT_MAX / 4 ?
> +				      conf->checkint * 4 : UINT_MAX);
> +	} else if (conf->checkint == CHECKINT_UNDEF)
> +		conf->checkint = (conf->max_checkint >= 4 ?
> +				  conf->max_checkint / 4 : 1);
> +	else if (conf->checkint > conf->max_checkint)
> +		conf->checkint = conf->max_checkint;
> +	condlog(3, "polling interval: %d, max: %d",
> +		conf->checkint, conf->max_checkint);
> +
>  	if (conf->blist_devnode == NULL) {
>  		conf->blist_devnode = vector_alloc();
>  
> diff --git a/libmultipath/config.h b/libmultipath/config.h
> index 2ab7b42c..a078947c 100644
> --- a/libmultipath/config.h
> +++ b/libmultipath/config.h
> @@ -139,6 +139,7 @@ struct config {
>  	int minio_rq;
>  	unsigned int checkint;
>  	unsigned int max_checkint;
> +	bool use_watchdog;
>  	int pgfailback;
>  	int remove;
>  	int rr_weight;
> diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
> index d7034655..e5ee6afe 100644
> --- a/libmultipath/defaults.h
> +++ b/libmultipath/defaults.h
> @@ -53,9 +53,8 @@
>  /* Enable all foreign libraries by default */
>  #define DEFAULT_ENABLE_FOREIGN ""
>  
> -#define CHECKINT_UNDEF		(~0U)
> +#define CHECKINT_UNDEF		UINT_MAX
>  #define DEFAULT_CHECKINT	5
> -#define MAX_CHECKINT(a)		(a << 2)
>  
>  #define MAX_DEV_LOSS_TMO	UINT_MAX
>  #define DEFAULT_PIDFILE		"/" RUN_DIR "/multipathd.pid"
> diff --git a/multipathd/main.c b/multipathd/main.c
> index c0423602..95426d3d 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -33,10 +33,6 @@
>   */
>  #include "checkers.h"
>  
> -#ifdef USE_SYSTEMD
> -static int use_watchdog;
> -#endif
> -
>  /*
>   * libmultipath
>   */
> @@ -2284,6 +2280,7 @@ checkerloop (void *ap)
>  	struct timespec last_time;
>  	struct config *conf;
>  	int foreign_tick = 0;
> +	bool use_watchdog;
>  
>  	pthread_cleanup_push(rcu_unregister, NULL);
>  	rcu_register_thread();
> @@ -2295,6 +2292,11 @@ checkerloop (void *ap)
>  	get_monotonic_time(&last_time);
>  	last_time.tv_sec -= 1;
>  
> +	/* use_watchdog is set from process environment and never changes */
> +	conf = get_multipath_config();
> +	use_watchdog = conf->use_watchdog;
> +	put_multipath_config(conf);
> +
>  	while (1) {
>  		struct timespec diff_time, start_time, end_time;
>  		int num_paths = 0, strict_timing, rc = 0;
> @@ -2766,7 +2768,6 @@ child (__attribute__((unused)) void *param)
>  	struct multipath * mpp;
>  	int i;
>  #ifdef USE_SYSTEMD
> -	unsigned long checkint;
>  	int startup_done = 0;
>  #endif
>  	int rc;
> @@ -2843,21 +2844,6 @@ child (__attribute__((unused)) void *param)
>  	setscheduler();
>  	set_oom_adj();
>  
> -#ifdef USE_SYSTEMD
> -	envp = getenv("WATCHDOG_USEC");
> -	if (envp && sscanf(envp, "%lu", &checkint) == 1) {
> -		/* Value is in microseconds */
> -		conf->max_checkint = checkint / 1000000;
> -		/* Rescale checkint */
> -		if (conf->checkint > conf->max_checkint)
> -			conf->checkint = conf->max_checkint;
> -		else
> -			conf->checkint = conf->max_checkint / 4;
> -		condlog(3, "enabling watchdog, interval %d max %d",
> -			conf->checkint, conf->max_checkint);
> -		use_watchdog = conf->checkint;
> -	}
> -#endif
>  	/*
>  	 * Startup done, invalidate configuration
>  	 */
> -- 
> 2.24.0




More information about the dm-devel mailing list