--- linux-last/include/linux/dm-ioctl.h	Wed Nov 14 14:42:24 2001
+++ linux/include/linux/dm-ioctl.h	Tue Nov 20 10:02:43 2001
@@ -47,7 +47,7 @@
 #define DM_IOCTL 0xfd
 #define DM_CHAR_MAJOR 124
 
-#define	DM_CREATE _IOW(DM_IOCTL, 0x00, struct dm_ioctl)
+#define	DM_CREATE _IOWR(DM_IOCTL, 0x00, struct dm_ioctl)
 #define	DM_REMOVE _IOW(DM_IOCTL, 0x01, struct dm_ioctl)
 #define	DM_SUSPEND _IOW(DM_IOCTL, 0x02, struct dm_ioctl)
 #define	DM_RELOAD _IOWR(DM_IOCTL, 0x03, struct dm_ioctl)
--- linux-last/drivers/md/dm-linear.c	Wed Nov 14 14:42:24 2001
+++ linux/drivers/md/dm-linear.c	Wed Nov 14 20:13:15 2001
@@ -112,4 +112,3 @@
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
 #endif
-
--- linux-last/drivers/md/dm-ioctl.c	Wed Nov 14 14:42:24 2001
+++ linux/drivers/md/dm-ioctl.c	Tue Nov 20 10:32:47 2001
@@ -134,7 +134,33 @@
 	return r;
 }
 
-static int create(struct dm_ioctl *param)
+/*
+ * Copies device info back to user space, used by
+ * the create and info ioctls.
+ */
+static int info(const char *name, struct dm_ioctl *user)
+{
+	struct dm_ioctl param;
+	struct mapped_device *md = dm_get(name);
+
+	if (!md) {
+		param.exists = 0;
+		goto out;
+	}
+
+	param.data_size = 0;
+	strncpy(param.name, md->name, sizeof(param.name));
+	param.exists = 1;
+	param.suspend = md->suspended;
+	param.open_count = md->use_count;
+	param.minor = MINOR(md->dev);
+	param.target_count = md->map->num_targets;
+
+ out:
+	return copy_to_user(user, &param, sizeof(param));
+}
+
+static int create(struct dm_ioctl *param, struct dm_ioctl *user)
 {
 	int r;
 	struct mapped_device *md;
@@ -143,15 +169,22 @@
 	if ((r = dm_table_create(&t)))
 		return r;
 
-	if ((r = populate_table(t, param))) {
-		dm_table_destroy(t);
-		return r;
-	}
+	if ((r = populate_table(t, param)))
+		goto bad;
 
 	if ((r = dm_create(param->name, param->minor, t, &md)))
-		return r;
+		goto bad;
+
+	if ((r = info(param->name, user))) {
+		dm_destroy(md);
+		goto bad;
+	}
 
 	return 0;
+
+ bad:
+	dm_table_destroy(t);
+	return r;
 }
 
 static int remove(struct dm_ioctl *param)
@@ -202,28 +235,6 @@
 	return 0;
 }
 
-static int info(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md = dm_get(param->name);
-
-	if (!md) {
-		param->exists = 0;
-		goto out;
-	}
-
-	param->exists = 1;
-	param->suspend = md->suspended;
-	param->open_count = md->use_count;
-	param->minor = MINOR(md->dev);
-	param->target_count = md->map->num_targets;
-
- out:
-	if (copy_to_user(user, param, sizeof(*param)))
-		return -EFAULT;
-
-	return 0;
-}
-
 static int ctl_open(struct inode *inode, struct file *file)
 {
 	/* only root can open this */
@@ -244,7 +255,7 @@
 static int ctl_ioctl(struct inode *inode, struct file *file,
 		     uint command, ulong a)
 {
-	int r = -EINVAL;
+	int r;
 	struct dm_ioctl *p;
 
 	if ((r = copy_params((struct dm_ioctl *) a, &p)))
@@ -252,7 +263,7 @@
 
 	switch (command) {
 	case DM_CREATE:
-		r = create(p);
+		r = create(p, (struct dm_ioctl *) a);
 		break;
 
 	case DM_REMOVE:
@@ -268,11 +279,12 @@
 		break;
 
 	case DM_INFO:
-		r = info(p, (struct dm_ioctl *) a);
+		r = info(p->name, (struct dm_ioctl *) a);
 		break;
 
 	default:
 		WARN("dm_ctl_ioctl: unknown command 0x%x\n", command);
+		r = -EINVAL;
 	}
 
 	free_params(p);
