]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/dm-ioctl.c
[PATCH] dm store geometry
[linux-2.6-omap-h63xx.git] / drivers / md / dm-ioctl.c
index 65826bdac00c7b3649c4815690cf64fc0d2faac2..8edd6435414df900777cbc78d4bf4988d0be37e1 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/dm-ioctl.h>
+#include <linux/hdreg.h>
 
 #include <asm/uaccess.h>
 
@@ -700,6 +701,54 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
        return dm_hash_rename(param->name, new_name);
 }
 
+static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
+{
+       int r = -EINVAL, x;
+       struct mapped_device *md;
+       struct hd_geometry geometry;
+       unsigned long indata[4];
+       char *geostr = (char *) param + param->data_start;
+
+       md = find_device(param);
+       if (!md)
+               return -ENXIO;
+
+       if (geostr < (char *) (param + 1) ||
+           invalid_str(geostr, (void *) param + param_size)) {
+               DMWARN("Invalid geometry supplied.");
+               goto out;
+       }
+
+       x = sscanf(geostr, "%lu %lu %lu %lu", indata,
+                  indata + 1, indata + 2, indata + 3);
+
+       if (x != 4) {
+               DMWARN("Unable to interpret geometry settings.");
+               goto out;
+       }
+
+       if (indata[0] > 65535 || indata[1] > 255 ||
+           indata[2] > 255 || indata[3] > ULONG_MAX) {
+               DMWARN("Geometry exceeds range limits.");
+               goto out;
+       }
+
+       geometry.cylinders = indata[0];
+       geometry.heads = indata[1];
+       geometry.sectors = indata[2];
+       geometry.start = indata[3];
+
+       r = dm_set_geometry(md, &geometry);
+       if (!r)
+               r = __dev_status(md, param);
+
+       param->data_size = 0;
+
+out:
+       dm_put(md);
+       return r;
+}
+
 static int do_suspend(struct dm_ioctl *param)
 {
        int r = 0;
@@ -1234,7 +1283,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd)
 
                {DM_LIST_VERSIONS_CMD, list_versions},
 
-               {DM_TARGET_MSG_CMD, target_message}
+               {DM_TARGET_MSG_CMD, target_message},
+               {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry}
        };
 
        return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;