8d49164
---
8d49164
 libmultipath/dict.c        |   12 ++++++++++++
8d49164
 libmultipath/print.c       |    2 ++
8d49164
 libmultipath/structs.h     |    3 ++-
8d49164
 multipath/multipath.conf.5 |    5 +++++
8d49164
 multipathd/main.c          |   29 ++++++++++++++++++++++++++++-
8d49164
 5 files changed, 49 insertions(+), 2 deletions(-)
8d49164
8d49164
Index: multipath-tools-120123/libmultipath/dict.c
8d49164
===================================================================
8d49164
--- multipath-tools-120123.orig/libmultipath/dict.c
8d49164
+++ multipath-tools-120123/libmultipath/dict.c
8d49164
@@ -406,6 +406,8 @@ default_failback_handler(vector strvec)
8d49164
 		conf->pgfailback = -FAILBACK_MANUAL;
8d49164
 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
8d49164
 		conf->pgfailback = -FAILBACK_IMMEDIATE;
8d49164
+	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
8d49164
+		conf->pgfailback = -FAILBACK_FOLLOWOVER;
8d49164
 	else
8d49164
 		conf->pgfailback = atoi(buff);
8d49164
 
8d49164
@@ -1031,6 +1033,8 @@ hw_failback_handler(vector strvec)
8d49164
 		hwe->pgfailback = -FAILBACK_MANUAL;
8d49164
 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
8d49164
 		hwe->pgfailback = -FAILBACK_IMMEDIATE;
8d49164
+	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
8d49164
+		hwe->pgfailback = -FAILBACK_FOLLOWOVER;
8d49164
 	else
8d49164
 		hwe->pgfailback = atoi(buff);
8d49164
 
8d49164
@@ -1303,6 +1307,8 @@ mp_failback_handler(vector strvec)
8d49164
 		mpe->pgfailback = -FAILBACK_MANUAL;
8d49164
 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
8d49164
 		mpe->pgfailback = -FAILBACK_IMMEDIATE;
8d49164
+	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
8d49164
+		mpe->pgfailback = -FAILBACK_FOLLOWOVER;
8d49164
 	else
8d49164
 		mpe->pgfailback = atoi(buff);
8d49164
 
8d49164
@@ -1646,6 +1652,8 @@ snprint_mp_failback (char * buff, int le
8d49164
 		return snprintf(buff, len, "manual");
8d49164
 	case -FAILBACK_IMMEDIATE:
8d49164
 		return snprintf(buff, len, "immediate");
8d49164
+	case -FAILBACK_FOLLOWOVER:
8d49164
+		return snprintf(buff, len, "followover");
8d49164
 	default:
8d49164
 		return snprintf(buff, len, "%i", mpe->pgfailback);
8d49164
 	}
8d49164
@@ -1985,6 +1993,8 @@ snprint_hw_failback (char * buff, int le
8d49164
 		return snprintf(buff, len, "manual");
8d49164
 	case -FAILBACK_IMMEDIATE:
8d49164
 		return snprintf(buff, len, "immediate");
8d49164
+	case -FAILBACK_FOLLOWOVER:
8d49164
+		return snprintf(buff, len, "followover");
8d49164
 	default:
8d49164
 		return snprintf(buff, len, "%i", hwe->pgfailback);
8d49164
 	}
8d49164
@@ -2243,6 +2253,8 @@ snprint_def_failback (char * buff, int l
8d49164
 		return snprintf(buff, len, "manual");
8d49164
 	case -FAILBACK_IMMEDIATE:
8d49164
 		return snprintf(buff, len, "immediate");
8d49164
+	case -FAILBACK_FOLLOWOVER:
8d49164
+		return snprintf(buff, len, "followover");
8d49164
 	default:
8d49164
 		return snprintf(buff, len, "%i", conf->pgfailback);
8d49164
 	}
8d49164
Index: multipath-tools-120123/libmultipath/print.c
8d49164
===================================================================
8d49164
--- multipath-tools-120123.orig/libmultipath/print.c
8d49164
+++ multipath-tools-120123/libmultipath/print.c
8d49164
@@ -143,6 +143,8 @@ snprint_failback (char * buff, size_t le
8d49164
 {
8d49164
 	if (mpp->pgfailback == -FAILBACK_IMMEDIATE)
8d49164
 		return snprintf(buff, len, "immediate");
8d49164
+	if (mpp->pgfailback == -FAILBACK_FOLLOWOVER)
8d49164
+		return snprintf(buff, len, "followover");
8d49164
 
8d49164
 	if (!mpp->failback_tick)
8d49164
 		return snprintf(buff, len, "-");
8d49164
Index: multipath-tools-120123/libmultipath/structs.h
8d49164
===================================================================
8d49164
--- multipath-tools-120123.orig/libmultipath/structs.h
8d49164
+++ multipath-tools-120123/libmultipath/structs.h
8d49164
@@ -39,7 +39,8 @@ enum rr_weight_mode {
8d49164
 enum failback_mode {
8d49164
 	FAILBACK_UNDEF,
8d49164
 	FAILBACK_MANUAL,
8d49164
-	FAILBACK_IMMEDIATE
8d49164
+	FAILBACK_IMMEDIATE,
8d49164
+	FAILBACK_FOLLOWOVER
8d49164
 };
8d49164
 
8d49164
 enum sysfs_buses {
8d49164
Index: multipath-tools-120123/multipathd/main.c
8d49164
===================================================================
8d49164
--- multipath-tools-120123.orig/multipathd/main.c
8d49164
+++ multipath-tools-120123/multipathd/main.c
8d49164
@@ -1011,6 +1011,32 @@ mpvec_garbage_collector (struct vectors
8d49164
 	}
8d49164
 }
8d49164
 
8d49164
+/* This is called after a path has started working again. It the multipath
8d49164
+ * device for this path uses the followover failback type, and this is the
8d49164
+ * best pathgroup, and this is the first path in the pathgroup to come back
8d49164
+ * up, then switch to this pathgroup */
8d49164
+static int
8d49164
+followover_should_failback(struct path * pp)
8d49164
+{
8d49164
+	struct pathgroup * pgp;
8d49164
+	struct path *pp1;
8d49164
+	int i;
8d49164
+
8d49164
+	if (pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER ||
8d49164
+	    !pp->mpp->pg || !pp->pgindex ||
8d49164
+	    pp->pgindex != pp->mpp->bestpg)
8d49164
+		return 0;
8d49164
+
8d49164
+	pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
8d49164
+	vector_foreach_slot(pgp->paths, pp1, i) {
8d49164
+		if (pp1 == pp)
8d49164
+			continue;
8d49164
+		if (pp1->state != PATH_DOWN && pp1->state != PATH_SHAKY)
8d49164
+			return 0;
8d49164
+	}
8d49164
+	return 1;
8d49164
+}
8d49164
+
8d49164
 static void
8d49164
 defered_failback_tick (vector mpvec)
8d49164
 {
8d49164
@@ -1238,7 +1264,8 @@ check_path (struct vectors * vecs, struc
8d49164
 		    (new_path_up || pp->mpp->failback_tick <= 0))
8d49164
 			pp->mpp->failback_tick =
8d49164
 				pp->mpp->pgfailback + 1;
8d49164
-		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE)
8d49164
+		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
8d49164
+			 followover_should_failback(pp))
8d49164
 			switch_pathgroup(pp->mpp);
8d49164
 	}
8d49164
 }
8d49164
Index: multipath-tools-120123/multipath/multipath.conf.5
8d49164
===================================================================
8d49164
--- multipath-tools-120123.orig/multipath/multipath.conf.5
8d49164
+++ multipath-tools-120123/multipath/multipath.conf.5
8d49164
@@ -258,6 +258,11 @@ active paths.
8d49164
 .B manual
8d49164
 Do not perform automatic failback.
8d49164
 .TP
8d49164
+.B followover
8d49164
+Only perform automatic failback when the first path of a pathgroup
8d49164
+becomes active. This keeps a node from automatically failing back when
8d49164
+another node requested the failover.
8d49164
+.TP
8d49164
 .B values > 0
8d49164
 deferred failback (time to defer in seconds)
8d49164
 .TP