[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[dm-devel] [PATCH RFC 1/3] make priority groups modular and rm ps's HW knowledge



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)

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]