Add switch_group message.
--- diff/drivers/md/dm-mpath.c 2004-11-10 15:12:30.000000000 +0000
+++ source/drivers/md/dm-mpath.c 2004-11-10 15:12:36.000000000 +0000
@@ -67,6 +67,7 @@
struct pgpath *current_pgpath;
struct priority_group *current_pg;
+ struct priority_group *next_pg; /* Switch to this PG if set */
unsigned current_count;
struct work_struct process_queued_ios;
@@ -239,6 +240,14 @@
if (!m->nr_valid_paths)
goto out;
+ /* Were we instructed to switch PG? */
+ if (m->next_pg) {
+ pgpath = __choose_path_in_pg(m, m->next_pg);
+ m->next_pg = NULL;
+ if (pgpath)
+ goto out;
+ }
+
/* Don't change PG until it has no remaining paths */
if (m->current_pg) {
pgpath = __choose_path_in_pg(m, m->current_pg);
@@ -823,6 +832,34 @@
schedule_work(&m->trigger_event);
}
+static int switch_pg_num(struct multipath *m, const char *pgstr)
+{
+ struct priority_group *pg;
+ unsigned pgnum;
+ unsigned long flags;
+
+ if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+ (pgnum > m->nr_priority_groups)) {
+ DMWARN("invalid PG number supplied to switch_pg_num");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&m->lock, flags);
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ pg->bypassed = 0;
+ if (--pgnum)
+ continue;
+
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+ m->next_pg = pg;
+ }
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ schedule_work(&m->trigger_event);
+ return 0;
+}
+
/*
* Set/clear bypassed status of a PG.
* PG numbering goes 1, 2, 3...
@@ -1072,6 +1109,8 @@
return bypass_pg_num(m, argv[1], 1);
else if (!strnicmp(argv[0], MESG_STR("enable_group")))
return bypass_pg_num(m, argv[1], 0);
+ else if (!strnicmp(argv[0], MESG_STR("switch_group")))
+ return switch_pg_num(m, argv[1]);
else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
action = reinstate_path;
else if (!strnicmp(argv[0], MESG_STR("fail_path")))