Allow PGs to be bypassed.
--- diff/drivers/md/dm-mpath.c	2004-10-29 15:37:46.000000000 +0100
+++ source/drivers/md/dm-mpath.c	2004-10-29 15:37:52.000000000 +0100
@@ -40,6 +40,7 @@
 	struct path_selector ps;
 
 	unsigned nr_paths;
+	unsigned bypass;
 	struct list_head paths;
 };
 
@@ -193,6 +194,8 @@
 	if (m->nr_valid_paths) {
 		/* loop through the priority groups until we find a valid path. */
 		list_for_each_entry (pg, &m->priority_groups, list) {
+			if (pg->bypass)
+				continue;
 			path = pg->ps.type->select_path(&pg->ps,
 							&m->current_count);
 			if (path)
@@ -630,6 +633,31 @@
 	return r;
 }
 
+/*
+ * Set/clear bypass status of a PG.
+ * PG numbering goes 1, 2, 3...
+ */
+static int bypass_pg(struct multipath *m, const char *pgstr, int bypass)
+{
+	struct priority_group *pg;
+	unsigned pgnum;
+
+	if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum)
+		goto error;
+
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		if (--pgnum)
+			continue;
+
+		pg->bypass = bypass;
+		return 0;
+	}
+
+error:
+	DMWARN("invalid PG number supplied to bypass_pg");
+	return -EINVAL;
+}
+
 static int do_end_io(struct multipath *m, struct bio *bio,
 		     int error, struct mpath_io *mpio)
 {
@@ -746,7 +774,11 @@
 	if (argc != 2)
 		goto error;
 
-	if (!strnicmp(argv[0], "reinstate", 10))
+	if (!strnicmp(argv[0], "disable_group", 14))
+		return bypass_pg(m, argv[1], 0);
+	else if (!strnicmp(argv[0], "enable_group", 13))
+		return bypass_pg(m, argv[1], 1);
+	else if (!strnicmp(argv[0], "reinstate", 10))
 		action = reinstate_path;
 	else if (!strnicmp(argv[0], "fail", 5))
 		action = fail_path;
