Add pg_init capability.
--- diff/drivers/md/dm-hw-handler.h	2004-10-29 15:38:04.000000000 +0100
+++ source/drivers/md/dm-hw-handler.h	2004-10-29 15:38:35.000000000 +0100
@@ -17,12 +17,16 @@
 	void *context;
 };
 
+struct path;
+
 /*
  * Constructs a hardware handler object, takes custom arguments
  */
 typedef int (*hwh_ctr_fn) (struct hw_handler *hwh, unsigned arc, char **argv);
 typedef void (*hwh_dtr_fn) (struct hw_handler *hwh);
 
+typedef int (*hwh_pg_init_fn) (struct hw_handler *hwh, struct path *path,
+			       struct block_device *bdev);
 typedef unsigned (*hwh_err_fn) (struct hw_handler *hwh, struct bio *bio);
 typedef	int (*hwh_status_fn) (struct hw_handler *hwh,
 			      status_type_t type,
@@ -36,6 +40,7 @@
 	hwh_ctr_fn ctr;
 	hwh_dtr_fn dtr;
 
+	hwh_pg_init_fn pg_init;
 	hwh_err_fn err;
 	hwh_status_fn status;
 };
@@ -60,4 +65,8 @@
 #define MP_BYPASS_PG 2
 #define MP_RETRY_IO  4
 
+/* hwh_pg_init_fn return values */
+#define MP_PG_INITIALISING 1
+#define MP_PG_FAILED 2
+
 #endif
--- diff/drivers/md/dm-mpath.c	2004-10-29 15:38:29.000000000 +0100
+++ source/drivers/md/dm-mpath.c	2004-10-29 15:38:35.000000000 +0100
@@ -59,6 +59,7 @@
 	unsigned nr_valid_paths;
 
 	struct path *current_path;
+	struct priority_group *current_pg;
 	unsigned current_count;
 
 	struct work_struct dispatch_queued;
@@ -187,24 +188,57 @@
 /*-----------------------------------------------------------------
  * The multipath daemon is responsible for resubmitting queued ios.
  *---------------------------------------------------------------*/
+
+/*
+ * Retuns 0 if pg switch failed else 1.
+ * Clears *path if it's not ready to be used.
+ */
+static int __switch_pg(struct multipath *m, struct path **path)
+{
+	int r;
+	struct hw_handler *hwh = &m->hw_handler;
+
+	if (!hwh || !hwh->type->pg_init)
+		return 1;
+
+	r = hwh->type->pg_init(hwh, *path, (*path)->dev->bdev);
+	if (r == MP_PG_INITIALISING) {
+		m->initialising_pg = 1;
+		*path = NULL;
+		return 1;
+	} else if (r == MP_PG_FAILED) {
+		(*path)->pg->bypass = 1;
+		return 0;
+	}
+
+	return 1;
+}
+
 static int __choose_path(struct multipath *m)
 {
 	struct priority_group *pg;
 	struct path *path = NULL;
 
 	if (m->nr_valid_paths) {
-		/* loop through the priority groups until we find a valid path. */
+		/* loop through 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)
-				break;
+			if (!path)
+				continue;
+
+			if (m->current_pg != pg && !__switch_pg(m, &path))
+				continue;
+
+			break;
 		}
 	}
 
 	m->current_path = path;
+	if (path)
+		m->current_pg = path->pg;
 
 	return 0;
 }
