01-sep-pg-from-mpath.patch - move some pg code out of dm-mpath.c. dm-mpath.c
still parses some args like how it does of selectors, but there is a new table
format:
num_groups [group-name num_group_args [selector-name num_selector_arg num_paths
[path_dev [path args (group args then selector args)]* ]+ ]+ ]+
The default group is just named "generic" and num_group_args=0.
dm-mpath.c | 257 +++++++++++++++++++++++++++++++++++++------------------------
1 files changed, 157 insertions(+), 100 deletions(-)
--- linux-2.6.7-rc2/drivers/md/dm-mpath.c 2004-06-04 03:52:23.332727408 -0700
+++ linux-2.6.7-rc2-pg/drivers/md/dm-mpath.c 2004-06-04 03:37:30.871140637 -0700
@@ -1,11 +1,16 @@
/*
+ * dm-mpath.c - maps/remaps IO by interfacing with DM
+ * priority_groups and path_selectors.
+ *
* Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004 IBM Corporation
*
* This file is released under the GPL.
*/
#include "dm.h"
#include "dm-path-selector.h"
+#include "dm-priority-group.h"
#include "dm-bio-list.h"
#include "dm-bio-record.h"
@@ -30,20 +35,9 @@ struct path {
inline struct block_device *dm_path_to_bdev(struct path *path)
{
- return path->dev->bdev;
+ return (path ? path->dev->bdev : NULL);
}
-
-struct priority_group {
- struct list_head list;
-
- struct multipath *m;
- struct path_selector ps;
-
- unsigned nr_paths;
- struct list_head paths;
-};
-
-#define ps_to_pg(__ps) container_of((__ps), struct priority_group, ps)
+EXPORT_SYMBOL(dm_path_to_bdev);
/* Multipath context */
struct multipath {
@@ -126,6 +120,11 @@ static void free_priority_group(struct p
{
struct path_selector *ps = &pg->ps;
+ if (pg->type) {
+ pg->type->dtr(pg);
+ dm_put_priority_group(pg->type);
+ }
+
if (ps->type) {
ps->type->dtr(ps);
dm_put_path_selector(ps->type);
@@ -172,8 +171,7 @@ static void free_multipath(struct multip
kfree(m);
}
-static void __ps_init_complete(struct multipath *m,
- struct priority_group *pg)
+static void __pg_init_complete(struct multipath *m, struct priority_group *pg)
{
m->initializing_pg = 0;
m->current_pg = pg;
@@ -181,18 +179,17 @@ static void __ps_init_complete(struct mu
schedule_work(&m->dispatch_failed);
}
-void dm_ps_init_complete(struct path_selector *ps)
+void dm_pg_init_complete(struct priority_group *pg)
{
unsigned long flags;
- struct priority_group *pg = ps_to_pg(ps);
struct multipath *m = pg->m;
spin_lock_irqsave(&m->lock, flags);
- __ps_init_complete(m, pg);
+ __pg_init_complete(m, pg);
spin_unlock_irqrestore(&m->lock, flags);
}
-EXPORT_SYMBOL(dm_ps_init_complete);
+EXPORT_SYMBOL(dm_pg_init_complete);
static int select_group(struct multipath *m, struct mpath_io *mpio,
struct bio *bio)
@@ -206,14 +203,14 @@ static int select_group(struct multipath
list_for_each_entry (pg, &m->priority_groups, list) {
- if (pg->ps.type->init) {
+ if (pg->type->init) {
spin_unlock_irq(&m->lock);
- err = pg->ps.type->init(&pg->ps);
+ err = pg->type->init(pg);
spin_lock_irq(&m->lock);
- if (err == DM_PS_INITIALIZING)
- return DM_PS_INITIALIZING;
- else if (err == DM_PS_FAILED)
+ if (err == DM_PG_INITIALIZING)
+ return DM_PG_INITIALIZING;
+ else if (err == DM_PG_FAILED)
continue;
}
@@ -223,11 +220,11 @@ static int select_group(struct multipath
break;
}
- __ps_init_complete(m, mpio->path ? pg : NULL);
- return mpio->path ? DM_PS_SUCCESS : DM_PS_FAILED;
+ __pg_init_complete(m, mpio->path ? pg : NULL);
+ return mpio->path ? DM_PG_SUCCESS : DM_PG_FAILED;
}
-static int select_path1(struct multipath *m, struct mpath_io *mpio,
+static int select_path(struct multipath *m, struct mpath_io *mpio,
struct bio *bio, int wait)
{
mpio->path = NULL;
@@ -253,7 +250,7 @@ static int select_path1(struct multipath
mpio->path = ps->type->select_path(ps, bio, &mpio->info);
if (!mpio->path &&
- (select_group(m, mpio, bio) == DM_PS_INITIALIZING))
+ (select_group(m, mpio, bio) == DM_PG_INITIALIZING))
/*
* while the lock was dropped the
* initialization might have completed.
@@ -270,7 +267,7 @@ static int map_io(struct multipath *m, s
int err;
spin_lock_irq(&m->lock);
- err = select_path1(m, mpio, bio, wait);
+ err = select_path(m, mpio, bio, wait);
if (err == -EWOULDBLOCK)
/*
* when the ps init is completed it will
@@ -383,40 +380,56 @@ static void consume(struct arg_set *as,
as->argv += n;
}
-static struct path *parse_path(struct arg_set *as, struct path_selector *ps,
- struct dm_target *ti)
+static int parse_paths(struct arg_set *as, struct priority_group *pg,
+ int nr_pg_args, int nr_ps_args, struct dm_target *ti)
{
- int r;
struct path *p;
+ struct path_selector *ps = &pg->ps;
+ int i, r, nr_params = nr_pg_args + nr_ps_args + 1;
- /* we need at least a path arg */
- if (as->argc < 1) {
- ti->error = ESTR("no device given");
- return NULL;
- }
+ for (i = 0; i < pg->nr_paths; i++) {
+
+ if (as->argc < nr_params)
+ return -EINVAL;
- p = alloc_path();
- if (!p)
- return NULL;
+ /* we need at least a path arg */
+ if (as->argc < 1) {
+ ti->error = ESTR("no device given");
+ return -EINVAL;
+ }
- r = dm_get_device(ti, shift(as), ti->begin, ti->len,
- dm_table_get_mode(ti->table), &p->dev);
- if (r) {
- ti->error = ESTR("error getting device");
- goto bad;
- }
+ p = alloc_path();
+ if (!p)
+ return -EINVAL;
+
+ r = dm_get_device(ti, shift(as), ti->begin, ti->len,
+ dm_table_get_mode(ti->table), &p->dev);
+ if (r) {
+ ti->error = ESTR("error getting device");
+ goto free_path;
+ }
- r = ps->type->add_path(ps, p, as->argc, as->argv, &ti->error);
- if (r) {
- dm_put_device(ti, p->dev);
- goto bad;
+ r = pg->type->add_path(pg, p, nr_pg_args, as->argv, &ti->error);
+ if (r)
+ goto put_dev;
+ consume(as, nr_pg_args);
+
+ r = ps->type->add_path(ps, p, nr_ps_args, as->argv, &ti->error);
+ if (r)
+ goto put_dev;
+ consume(as, nr_ps_args);
+
+ p->pg = pg;
+ list_add_tail(&p->list, &pg->paths);
}
- return p;
+ return 0;
- bad:
+ put_dev:
+ dm_put_device(ti, p->dev);
+ free_path:
free_path(p);
- return NULL;
+ return -EINVAL;
}
static struct priority_group *parse_priority_group(struct arg_set *as,
@@ -424,16 +437,18 @@ static struct priority_group *parse_prio
struct dm_target *ti)
{
static struct param _params[] = {
+ {0, 1024, ESTR("invalid number of group args")},
+ {0, 1024, ESTR("invalid number of selector args")},
{1, 1024, ESTR("invalid number of paths")},
- {0, 1024, ESTR("invalid number of selector args")}
};
int r;
- unsigned i, nr_selector_args, nr_params;
+ unsigned nr_selector_args, nr_group_args;
struct priority_group *pg;
struct path_selector_type *pst;
+ struct priority_group_type *pgt;
- if (as->argc < 2) {
+ if (as->argc < 3) {
as->argc = 0;
ti->error = ESTR("not enough priority group aruments");
return NULL;
@@ -446,6 +461,29 @@ static struct priority_group *parse_prio
}
pg->m = m;
+ /* setup group */
+ pgt = dm_get_priority_group(shift(as));
+ if (!pgt) {
+ ti->error = ESTR("unknown priority group type");
+ goto bad;
+ }
+
+ r = pgt->ctr(pg);
+ if (r) {
+ dm_put_priority_group(pgt);
+ goto bad;
+ }
+ pg->type = pgt;
+
+ /*
+ * get num pg args per path. We might need
+ * per group args too?
+ */
+ r = read_param(_params, shift(as), &nr_group_args, &ti->error);
+ if (r)
+ goto bad;
+
+ /* setup selector */
pst = dm_get_path_selector(shift(as));
if (!pst) {
ti->error = ESTR("unknown path selector type");
@@ -459,38 +497,20 @@ static struct priority_group *parse_prio
}
pg->ps.type = pst;
- /*
- * read the paths
- */
- r = read_param(_params, shift(as), &pg->nr_paths, &ti->error);
+ /* num selector args */
+ r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
if (r)
goto bad;
- r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
+ /*
+ * read the paths
+ */
+ r = read_param(_params + 2, shift(as), &pg->nr_paths, &ti->error);
if (r)
goto bad;
- nr_params = 1 + nr_selector_args;
- for (i = 0; i < pg->nr_paths; i++) {
- struct path *path;
- struct arg_set path_args;
-
- if (as->argc < nr_params)
- goto bad;
-
- path_args.argc = nr_params;
- path_args.argv = as->argv;
-
- path = parse_path(&path_args, &pg->ps, ti);
- if (!path)
- goto bad;
-
- path->pg = pg;
- list_add_tail(&path->list, &pg->paths);
- consume(as, nr_params);
- }
-
- return pg;
+ if (!parse_paths(as, pg, nr_group_args, nr_selector_args, ti))
+ return pg;
bad:
free_priority_group(pg, ti);
@@ -573,10 +593,16 @@ static int multipath_map(struct dm_targe
static int do_end_io(struct multipath *m, struct bio *bio,
int error, struct mpath_io *mpio)
{
- struct path_selector *ps = &mpio->path->pg->ps;
+ struct priority_group *pg = mpio->path->pg;
+
+ if (pg->ps.type->end_io)
+ pg->ps.type->end_io(&pg->ps, bio, error, &mpio->info);
- ps->type->end_io(ps, bio, error, &mpio->info);
if (error) {
+ struct path *path = mpio->path;
+
+ if (pg->type->update_path(pg, path, error))
+ pg->ps.type->update_path(&pg->ps, path, error);
dm_bio_restore(&mpio->details, bio);
@@ -625,10 +651,11 @@ static int multipath_end_io(struct dm_ta
/*
* Info string has the following format:
- * num_groups [num_paths num_selector_args [path_dev A|F fail_count [selector_args]* ]+ ]+
+ * num_groups [num_paths [path_dev num_group_args A|F fail_count [group_args]* [num_selector_args [selector_args]* ]+ ]+
*
* Table string has the following format (identical to the constructor string):
- * num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
+ * num_groups [group-name num_group_args [selector-name num_selector_arg num_paths [path_dev [path args (group args then selector args)]* ]+ ]+ ]+
+ *
*/
static int multipath_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
@@ -647,13 +674,24 @@ static int multipath_status(struct dm_ta
EMIT("%u ", m->nr_priority_groups);
list_for_each_entry(pg, &m->priority_groups, list) {
- EMIT("%u %u ", pg->nr_paths, pg->ps.type->info_args);
+ EMIT("%u ", pg->nr_paths);
list_for_each_entry(p, &pg->paths, list) {
format_dev_t(buffer, p->dev->bdev->bd_dev);
EMIT("%s ", buffer);
- sz += pg->ps.type->status(&pg->ps, p, type,
- result + sz, maxlen - sz);
+
+ /* pg stat */
+ EMIT("%u ", pg->type->info_args);
+ sz += pg->type->status(pg, p, type,
+ result + sz,
+ maxlen - sz);
+ /* ps stat */
+ EMIT("%u ", pg->ps.type->info_args);
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps, p,
+ type,
+ result + sz,
+ maxlen - sz);
}
}
break;
@@ -662,14 +700,23 @@ static int multipath_status(struct dm_ta
EMIT("%u ", m->nr_priority_groups);
list_for_each_entry(pg, &m->priority_groups, list) {
- EMIT("%s %u %u ", pg->ps.type->name,
- pg->nr_paths, pg->ps.type->table_args);
+ EMIT("%s %u %s %u %u ", pg->type->name,
+ pg->type->table_args, pg->ps.type->name,
+ pg->ps.type->table_args, pg->nr_paths);
list_for_each_entry(p, &pg->paths, list) {
format_dev_t(buffer, p->dev->bdev->bd_dev);
EMIT("%s ", buffer);
- sz += pg->ps.type->status(&pg->ps, p, type,
- result + sz, maxlen - sz);
+ /* pg stat */
+ sz += pg->type->status(pg, p, type,
+ result + sz,
+ maxlen - sz);
+ /* ps stat */
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps, p,
+ type,
+ result + sz,
+ maxlen - sz);
}
}
@@ -706,18 +753,27 @@ static int __init dm_multipath_init(void
r = dm_register_target(&multipath_target);
if (r < 0) {
DMERR("%s: register failed %d", multipath_target.name, r);
- kmem_cache_destroy(_mpio_cache);
- return -EINVAL;
+ r = -EINVAL;
+ goto destroy_cache;
}
r = dm_register_path_selectors();
- if (r && r != -EEXIST) {
- dm_unregister_target(&multipath_target);
- kmem_cache_destroy(_mpio_cache);
- return r;
- }
+ if (r && r != -EEXIST)
+ goto unreg_tgt;
+
+ r = dm_register_generic_group();
+ if (r && r != -EEXIST)
+ goto unreg_ps;
DMINFO("dm_multipath v0.2.0");
+ return 0;
+
+unreg_ps:
+ dm_unregister_path_selectors();
+unreg_tgt:
+ dm_unregister_target(&multipath_target);
+destroy_cache:
+ kmem_cache_destroy(_mpio_cache);
return r;
}
@@ -725,6 +781,7 @@ static void __exit dm_multipath_exit(voi
{
int r;
+ dm_unregister_generic_group();
dm_unregister_path_selectors();
r = dm_unregister_target(&multipath_target);
if (r < 0)