[dm-devel] [PATCH][RESEND] multipath: add followover failback mode

Christophe Varoqui christophe.varoqui at gmail.com
Fri Aug 17 20:03:38 UTC 2012


On ven., 2012-07-27 at 15:56 -0500, Benjamin Marzinski wrote:
> This patch adds a new failback mode, followover, to deal with multiple
> computers accessing the same active/passive storage devices.  In these
> cases, if only one node loses access to the primary paths, it will
> force a trespass to the secondary paths.  If the nodes are configured
> with immediate failback, the other nodes with trespass back to the
> primary paths, and the machines will ping-pong the storage. If the
> nodes are configured with manual failback, this won't happen. However
> when the primary path is restored on the node that lost access to it,
> the nodes won't automatically failback to it.  In followover mode, they
> will.
> 
> Followover mode works by only failing back when a path comes back online
> from a pathgroup that previously had no working paths.  For this to
> work, the paths need an additional attribute, chkrstate. This is just like
> the path state, except it is not updated when the paths state is changed
> by the kernel, only when the path checker function sees that the path is
> down.  This is necessary because when a trespass occurs, all the outstanding
> IO to the previously active paths will fail, and the kernel will mark the
> path as down.  But for failback to happen in followover mode, the paths must
> actually be down, not just in a ghost state.
> 
Applied.

Good feature indeed.

> Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
> ---
>  libmultipath/dict.c        |   12 ++++++++++++
>  libmultipath/discovery.c   |    6 +++---
>  libmultipath/print.c       |    2 ++
>  libmultipath/structs.h     |    4 +++-
>  multipath/main.c           |    2 +-
>  multipath/multipath.conf.5 |    5 +++++
>  multipathd/main.c          |   35 ++++++++++++++++++++++++++++++++++-
>  7 files changed, 60 insertions(+), 6 deletions(-)
> 
> Index: multipath-tools-120518/libmultipath/dict.c
> ===================================================================
> --- multipath-tools-120518.orig/libmultipath/dict.c
> +++ multipath-tools-120518/libmultipath/dict.c
> @@ -398,6 +398,8 @@ default_failback_handler(vector strvec)
>  		conf->pgfailback = -FAILBACK_MANUAL;
>  	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
>  		conf->pgfailback = -FAILBACK_IMMEDIATE;
> +	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
> +		conf->pgfailback = -FAILBACK_FOLLOWOVER;
>  	else
>  		conf->pgfailback = atoi(buff);
>  
> @@ -1053,6 +1055,8 @@ hw_failback_handler(vector strvec)
>  		hwe->pgfailback = -FAILBACK_MANUAL;
>  	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
>  		hwe->pgfailback = -FAILBACK_IMMEDIATE;
> +	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
> +		hwe->pgfailback = -FAILBACK_FOLLOWOVER;
>  	else
>  		hwe->pgfailback = atoi(buff);
>  
> @@ -1351,6 +1355,8 @@ mp_failback_handler(vector strvec)
>  		mpe->pgfailback = -FAILBACK_MANUAL;
>  	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
>  		mpe->pgfailback = -FAILBACK_IMMEDIATE;
> +	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
> +		mpe->pgfailback = -FAILBACK_FOLLOWOVER;
>  	else
>  		mpe->pgfailback = atoi(buff);
>  
> @@ -1769,6 +1775,8 @@ snprint_mp_failback (char * buff, int le
>  		return snprintf(buff, len, "manual");
>  	case -FAILBACK_IMMEDIATE:
>  		return snprintf(buff, len, "immediate");
> +	case -FAILBACK_FOLLOWOVER:
> +		return snprintf(buff, len, "followover");
>  	default:
>  		return snprintf(buff, len, "%i", mpe->pgfailback);
>  	}
> @@ -2130,6 +2138,8 @@ snprint_hw_failback (char * buff, int le
>  		return snprintf(buff, len, "manual");
>  	case -FAILBACK_IMMEDIATE:
>  		return snprintf(buff, len, "immediate");
> +	case -FAILBACK_FOLLOWOVER:
> +		return snprintf(buff, len, "followover");
>  	default:
>  		return snprintf(buff, len, "%i", hwe->pgfailback);
>  	}
> @@ -2394,6 +2404,8 @@ snprint_def_failback (char * buff, int l
>  		return snprintf(buff, len, "manual");
>  	case -FAILBACK_IMMEDIATE:
>  		return snprintf(buff, len, "immediate");
> +	case -FAILBACK_FOLLOWOVER:
> +		return snprintf(buff, len, "followover");
>  	default:
>  		return snprintf(buff, len, "%i", conf->pgfailback);
>  	}
> Index: multipath-tools-120518/libmultipath/print.c
> ===================================================================
> --- multipath-tools-120518.orig/libmultipath/print.c
> +++ multipath-tools-120518/libmultipath/print.c
> @@ -143,6 +143,8 @@ snprint_failback (char * buff, size_t le
>  {
>  	if (mpp->pgfailback == -FAILBACK_IMMEDIATE)
>  		return snprintf(buff, len, "immediate");
> +	if (mpp->pgfailback == -FAILBACK_FOLLOWOVER)
> +		return snprintf(buff, len, "followover");
>  
>  	if (!mpp->failback_tick)
>  		return snprintf(buff, len, "-");
> Index: multipath-tools-120518/libmultipath/structs.h
> ===================================================================
> --- multipath-tools-120518.orig/libmultipath/structs.h
> +++ multipath-tools-120518/libmultipath/structs.h
> @@ -39,7 +39,8 @@ enum rr_weight_mode {
>  enum failback_mode {
>  	FAILBACK_UNDEF,
>  	FAILBACK_MANUAL,
> -	FAILBACK_IMMEDIATE
> +	FAILBACK_IMMEDIATE,
> +	FAILBACK_FOLLOWOVER
>  };
>  
>  enum sysfs_buses {
> @@ -151,6 +152,7 @@ struct path {
>  	int offline;
>  	int state;
>  	int dmstate;
> +	int chkrstate;
>  	int failcount;
>  	int priority;
>  	int pgindex;
> Index: multipath-tools-120518/multipathd/main.c
> ===================================================================
> --- multipath-tools-120518.orig/multipathd/main.c
> +++ multipath-tools-120518/multipathd/main.c
> @@ -995,6 +995,32 @@ mpvec_garbage_collector (struct vectors
>  	}
>  }
>  
> +/* This is called after a path has started working again. It the multipath
> + * device for this path uses the followover failback type, and this is the
> + * best pathgroup, and this is the first path in the pathgroup to come back
> + * up, then switch to this pathgroup */
> +static int
> +followover_should_failback(struct path * pp)
> +{
> +	struct pathgroup * pgp;
> +	struct path *pp1;
> +	int i;
> +
> +	if (pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER ||
> +	    !pp->mpp->pg || !pp->pgindex ||
> +	    pp->pgindex != pp->mpp->bestpg)
> +		return 0;
> +
> +	pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
> +	vector_foreach_slot(pgp->paths, pp1, i) {
> +		if (pp1 == pp)
> +			continue;
> +		if (pp1->chkrstate != PATH_DOWN && pp1->chkrstate != PATH_SHAKY)
> +			return 0;
> +	}
> +	return 1;
> +}
> +
>  static void
>  defered_failback_tick (vector mpvec)
>  {
> @@ -1092,6 +1118,8 @@ check_path (struct vectors * vecs, struc
>  {
>  	int newstate;
>  	int new_path_up = 0;
> +	int chkr_new_path_up = 0;
> +	int oldchkrstate = pp->chkrstate;
>  
>  	if (!pp->mpp)
>  		return;
> @@ -1130,6 +1158,7 @@ check_path (struct vectors * vecs, struc
>  			pp->dev);
>  		pp->dmstate = PSTATE_UNDEF;
>  	}
> +	pp->chkrstate = newstate;
>  	if (newstate != pp->state) {
>  		int oldstate = pp->state;
>  		pp->state = newstate;
> @@ -1182,6 +1211,9 @@ check_path (struct vectors * vecs, struc
>  
>  		new_path_up = 1;
>  
> +		if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
> +			chkr_new_path_up = 1;
> +
>  		/*
>  		 * if at least one path is up in a group, and
>  		 * the group is disabled, re-enable it
> @@ -1233,7 +1265,8 @@ check_path (struct vectors * vecs, struc
>  		    (new_path_up || pp->mpp->failback_tick <= 0))
>  			pp->mpp->failback_tick =
>  				pp->mpp->pgfailback + 1;
> -		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE)
> +		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
> +			 (chkr_new_path_up && followover_should_failback(pp)))
>  			switch_pathgroup(pp->mpp);
>  	}
>  }
> Index: multipath-tools-120518/multipath/multipath.conf.5
> ===================================================================
> --- multipath-tools-120518.orig/multipath/multipath.conf.5
> +++ multipath-tools-120518/multipath/multipath.conf.5
> @@ -254,6 +254,11 @@ active paths.
>  .B manual
>  Do not perform automatic failback.
>  .TP
> +.B followover
> +Only perform automatic failback when the first path of a pathgroup
> +becomes active. This keeps a node from automatically failing back when
> +another node requested the failover.
> +.TP
>  .B values > 0
>  deferred failback (time to defer in seconds)
>  .TP
> Index: multipath-tools-120518/libmultipath/discovery.c
> ===================================================================
> --- multipath-tools-120518.orig/libmultipath/discovery.c
> +++ multipath-tools-120518/libmultipath/discovery.c
> @@ -878,13 +878,13 @@ pathinfo (struct path *pp, vector hwtabl
>  
>  	if (mask & DI_CHECKER) {
>  		if (path_state == PATH_UP) {
> -			pp->state = get_state(pp, 0);
> +			pp->chkrstate = pp->state = get_state(pp, 0);
>  			if (pp->state == PATH_UNCHECKED ||
>  			    pp->state == PATH_WILD)
>  				goto blank;
>  		} else {
>  			condlog(3, "%s: path inaccessible", pp->dev);
> -			pp->state = path_state;
> +			pp->chkrstate = pp->state = path_state;
>  		}
>  	}
>  
> @@ -912,7 +912,7 @@ blank:
>  	 * Recoverable error, for example faulty or offline path
>  	 */
>  	memset(pp->wwid, 0, WWID_SIZE);
> -	pp->state = PATH_DOWN;
> +	pp->chkrstate = pp->state = PATH_DOWN;
>  
>  	return 0;
>  }
> Index: multipath-tools-120518/multipath/main.c
> ===================================================================
> --- multipath-tools-120518.orig/multipath/main.c
> +++ multipath-tools-120518/multipath/main.c
> @@ -144,7 +144,7 @@ update_paths (struct multipath * mpp)
>  					/*
>  					 * path is not in sysfs anymore
>  					 */
> -					pp->state = PATH_DOWN;
> +					pp->chkrstate = pp->state = PATH_DOWN;
>  					continue;
>  				}
>  				pp->mpp = mpp;






More information about the dm-devel mailing list