|
@@ -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;
|