diff -arup linux-2.6.5-orig/drivers/md/dm-mpath.c linux-2.6.5-psargs/drivers/md/dm-mpath.c --- linux-2.6.5-orig/drivers/md/dm-mpath.c 2004-04-18 20:34:44.000000000 -0700 +++ linux-2.6.5-psargs/drivers/md/dm-mpath.c 2004-04-18 22:29:27.991470346 -0700 @@ -324,8 +324,8 @@ static void trigger_event(void *data) /*----------------------------------------------------------------- * Constructor/argument parsing: - * [ - * [ []* ]+ ]+ + * [ []* + * [ []* ]+ ]+ *---------------------------------------------------------------*/ struct param { unsigned min; @@ -420,7 +420,7 @@ static struct priority_group *parse_prio }; int r; - unsigned i, nr_selector_args, nr_params; + unsigned i, nr_args; struct priority_group *pg; struct path_selector_type *pst; @@ -443,34 +443,47 @@ static struct priority_group *parse_prio goto bad; } - r = pst->ctr(pg->ps); + /* + * nr selector args + */ + r = read_param(_params + 1, shift(as), &nr_args, &ti->error); + if (r) + goto bad; + if (as->argc < nr_args) + goto bad; + + r = pst->ctr(pg->ps, nr_args, as->argv, &ti->error); if (r) { /* FIXME: need to put the pst ? fix after * factoring out the register */ goto bad; } pg->ps->type = pst; + consume(as, nr_args); /* - * read the paths + * nr path args */ - r = read_param(_params, shift(as), &pg->nr_paths, &ti->error); + r = read_param(_params + 1, shift(as), &nr_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, shift(as), &pg->nr_paths, &ti->error); if (r) goto bad; - nr_params = 1 + nr_selector_args; + nr_args += 1; for (i = 0; i < pg->nr_paths; i++) { struct path *path; struct arg_set path_args; - if (as->argc < nr_params) + if (as->argc < nr_args) goto bad; - path_args.argc = nr_params; + path_args.argc = nr_args; path_args.argv = as->argv; path = parse_path(&path_args, pg->ps, ti); @@ -479,7 +492,7 @@ static struct priority_group *parse_prio path->pg = pg; list_add_tail(&path->list, &pg->paths); - consume(as, nr_params); + consume(as, nr_args); } return pg; @@ -617,10 +630,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 [[selector_args]* num_paths [path_dev A|F fail_count [path_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 [selector-name num_selector_args [selector_args]* num_path_args num_paths + * [path_dev [path_args]* ]+ ]+ */ static int multipath_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) @@ -630,6 +644,7 @@ static int multipath_status(struct dm_ta struct priority_group *pg; struct path *p; char buffer[32]; + struct path_selector_type *pst; #define EMIT(x...) sz += ((sz >= maxlen) ? \ 0 : scnprintf(result + sz, maxlen - sz, x)) @@ -639,13 +654,18 @@ 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); + pst = pg->ps->type; + + sz += pst->ps_status(pg->ps, type, result + sz, + maxlen - sz); + 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); + sz += pst->path_status(pg->ps, p, type, + result + sz, + maxlen - sz); } } break; @@ -654,14 +674,19 @@ 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); + pst = pg->ps->type; + + EMIT("%s ", pst->name); + sz += pst->ps_status(pg->ps, type, result + sz, + maxlen - sz); + 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); - pg->ps->type->status(pg->ps, p, type, - result + sz, maxlen - sz); + sz += pst->path_status(pg->ps, p, type, + result + sz, + maxlen - sz); } } diff -arup linux-2.6.5-orig/drivers/md/dm-path-selector.c linux-2.6.5-psargs/drivers/md/dm-path-selector.c --- linux-2.6.5-orig/drivers/md/dm-path-selector.c 2004-04-18 20:34:44.000000000 -0700 +++ linux-2.6.5-psargs/drivers/md/dm-path-selector.c 2004-04-18 22:15:13.867049131 -0700 @@ -174,10 +174,17 @@ static struct selector *alloc_selector(v } /* Path selector constructor */ -static int rr_ctr(struct path_selector *ps) +static int rr_ctr(struct path_selector *ps, int argc, char **argv, + char **error) { struct selector *s; + /* parse the path-selector arguments */ + if (argc != 0) { + *error = "round-robin ps: incorrect number of arguments"; + return -EINVAL; + } + s = alloc_selector(); if (!s) return -ENOMEM; @@ -273,8 +280,8 @@ static struct path *rr_select_path(struc } /* Path status */ -static int rr_status(struct path_selector *ps, struct path *path, - status_type_t type, char *result, unsigned int maxlen) +static int rr_path_status(struct path_selector *ps, struct path *path, + status_type_t type, char *result, unsigned int maxlen) { unsigned long flags; struct path_info *pi; @@ -282,26 +289,39 @@ static int rr_status(struct path_selecto struct selector *s = (struct selector *) ps->context; int sz = 0; - if (type == STATUSTYPE_TABLE) - return 0; + if (type == STATUSTYPE_INFO) { - spin_lock_irqsave(&s->lock, flags); + spin_lock_irqsave(&s->lock, flags); - /* - * Is status called often for testing or something? - * If so maybe a ps's info should be allocated w/ path - * so a simple container_of can be used. - */ - pi = path_lookup(&s->valid_paths, path); - if (!pi) { - failed = 1; - pi = path_lookup(&s->invalid_paths, path); + /* + * Is status called often for testing or something? + * If so maybe a ps's info should be allocated w/ path + * so a simple container_of can be used. + */ + pi = path_lookup(&s->valid_paths, path); + if (!pi) { + failed = 1; + pi = path_lookup(&s->invalid_paths, path); + } + + sz = scnprintf(result, maxlen, "%s %u ", failed ? "F" : "A", + pi->fail_count); + + spin_unlock_irqrestore(&s->lock, flags); } - sz = scnprintf(result, maxlen, "%s %u ", failed ? "F" : "A", - pi->fail_count); + return sz; +} - spin_unlock_irqrestore(&s->lock, flags); +/* path selector status */ +static int rr_ps_status(struct path_selector *ps, status_type_t type, + char *result, unsigned int maxlen) +{ + int sz = 0; + + if (type == STATUSTYPE_TABLE) + /* []* */ + sz = scnprintf(result, maxlen, "0 0 "); return sz; } @@ -315,7 +335,8 @@ static struct path_selector_type rr_ps = .add_path = rr_add_path, .update_path = rr_update_path, .select_path = rr_select_path, - .status = rr_status, + .ps_status = rr_ps_status, + .path_status = rr_path_status, }; /* diff -arup linux-2.6.5-orig/drivers/md/dm-path-selector.h linux-2.6.5-psargs/drivers/md/dm-path-selector.h --- linux-2.6.5-orig/drivers/md/dm-path-selector.h 2004-04-18 20:34:44.000000000 -0700 +++ linux-2.6.5-psargs/drivers/md/dm-path-selector.h 2004-04-18 22:13:27.980742649 -0700 @@ -31,7 +31,8 @@ struct path_selector { /* * Constructs a path selector object, takes custom arguments */ -typedef int (*ps_ctr_fn) (struct path_selector *ps); +typedef int (*ps_ctr_fn) (struct path_selector *ps, int argc, char **argv, + char **error); typedef void (*ps_dtr_fn) (struct path_selector *ps); /* @@ -69,10 +70,13 @@ typedef void (*ps_update_path_fn) (struc * Table content based on parameters added in ps_add_path_fn * or path selector status */ -typedef int (*ps_status_fn) (struct path_selector *ps, - struct path *path, - status_type_t type, - char *result, unsigned int maxlen); +typedef int (*ps_path_status_fn) (struct path_selector *ps, + struct path *path, + status_type_t type, + char *result, unsigned int maxlen); +typedef int (*ps_selector_status_fn) (struct path_selector *ps, + status_type_t type, + char *result, unsigned int maxlen); /* Information about a path selector type */ struct path_selector_type { @@ -86,7 +90,8 @@ struct path_selector_type { ps_add_path_fn add_path; ps_update_path_fn update_path; ps_select_path_fn select_path; - ps_status_fn status; + ps_path_status_fn path_status; + ps_selector_status_fn ps_status; }; /*