From: Benjamin Marzinski <bmarzins@redhat.com>

This patch allows path errors from the multipath ctr function to
propagate up to userspace as errno values from the ioctl() call.

This is in response to
  https://www.redhat.com/archives/dm-devel/2008-May/msg00000.html
and
  https://bugzilla.redhat.com/show_bug.cgi?id=444421

The patch only lets through the errors that it needs to in order to
get the path errors from parse_path().

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
---
 drivers/md/dm-mpath.c |   22 ++++++++++++----------
 1 files changed, 12 insertions(+), 10 deletions(-)

Index: linux/drivers/md/dm-mpath.c
===================================================================
--- linux.orig/drivers/md/dm-mpath.c	2008-07-22 21:59:12.000000000 +0100
+++ linux/drivers/md/dm-mpath.c	2008-07-22 22:00:25.000000000 +0100
@@ -552,12 +552,12 @@ static struct pgpath *parse_path(struct 
 	/* we need at least a path arg */
 	if (as->argc < 1) {
 		ti->error = "no device given";
-		return NULL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	p = alloc_pgpath();
 	if (!p)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	r = dm_get_device(ti, shift(as), ti->begin, ti->len,
 			  dm_table_get_mode(ti->table), &p->path.dev);
@@ -576,7 +576,7 @@ static struct pgpath *parse_path(struct 
 
  bad:
 	free_pgpath(p);
-	return NULL;
+	return ERR_PTR(r);
 }
 
 static struct priority_group *parse_priority_group(struct arg_set *as,
@@ -594,14 +594,14 @@ static struct priority_group *parse_prio
 
 	if (as->argc < 2) {
 		as->argc = 0;
-		ti->error = "not enough priority group aruments";
-		return NULL;
+		ti->error = "not enough priority group arguments";
+		return ERR_PTR(-EINVAL);
 	}
 
 	pg = alloc_priority_group();
 	if (!pg) {
 		ti->error = "couldn't allocate priority group";
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 	pg->m = m;
 
@@ -634,8 +634,10 @@ static struct priority_group *parse_prio
 		path_args.argv = as->argv;
 
 		pgpath = parse_path(&path_args, &pg->ps, ti);
-		if (!pgpath)
+		if (IS_ERR(pgpath)) {
+			r = PTR_ERR(pgpath);
 			goto bad;
+		}
 
 		pgpath->pg = pg;
 		list_add_tail(&pgpath->list, &pg->pgpaths);
@@ -646,7 +648,7 @@ static struct priority_group *parse_prio
 
  bad:
 	free_priority_group(pg, ti);
-	return NULL;
+	return ERR_PTR(r);
 }
 
 static int parse_hw_handler(struct arg_set *as, struct multipath *m)
@@ -765,8 +767,8 @@ static int multipath_ctr(struct dm_targe
 		struct priority_group *pg;
 
 		pg = parse_priority_group(&as, m);
-		if (!pg) {
-			r = -EINVAL;
+		if (IS_ERR(pg)) {
+			r = PTR_ERR(pg);
 			goto bad;
 		}