diff -Naurp old/drivers/md/dm.c linux-2.6.16-rc3/drivers/md/dm.c --- old/drivers/md/dm.c 2006-02-15 10:49:46.000000000 -0800 +++ linux-2.6.16-rc3/drivers/md/dm.c 2006-02-15 10:42:14.000000000 -0800 @@ -17,6 +17,7 @@ #include #include #include +#include static const char *_name = DM_NAME; @@ -225,6 +226,16 @@ static int dm_blk_close(struct inode *in return 0; } +static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + int ret; + struct mapped_device *md = bdev->bd_disk->private_data; + + ret = dm_table_get_geometry(md->map, geo); + + return (ret ? 0 : -ENOTTY); +} + static inline struct dm_io *alloc_io(struct mapped_device *md) { return mempool_alloc(md->io_pool, GFP_NOIO); @@ -1242,6 +1253,7 @@ int dm_suspended(struct mapped_device *m static struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, + .getgeo = dm_blk_getgeo, .owner = THIS_MODULE }; diff -Naurp old/drivers/md/dm.h linux-2.6.16-rc3/drivers/md/dm.h --- old/drivers/md/dm.h 2006-02-15 10:49:46.000000000 -0800 +++ linux-2.6.16-rc3/drivers/md/dm.h 2006-02-13 17:35:24.000000000 -0800 @@ -123,6 +123,8 @@ void dm_table_resume_targets(struct dm_t int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); int dm_table_flush_all(struct dm_table *t); +int dm_table_get_geometry(struct dm_table *t, struct hd_geometry *geo); +int dm_table_set_geometry(struct dm_table *t, struct hd_geometry *geo); /*----------------------------------------------------------------- * A registry of target types. diff -Naurp old/drivers/md/dm-ioctl.c linux-2.6.16-rc3/drivers/md/dm-ioctl.c --- old/drivers/md/dm-ioctl.c 2006-02-15 10:49:46.000000000 -0800 +++ linux-2.6.16-rc3/drivers/md/dm-ioctl.c 2006-02-15 10:51:19.000000000 -0800 @@ -690,6 +690,35 @@ static int dev_rename(struct dm_ioctl *p return dm_hash_rename(param->name, new_name); } +static int dev_setgeo(struct dm_ioctl *param, size_t param_size) +{ + int r = 0; + size_t len; + struct mapped_device *md; + struct dm_table *tbl; + struct dm_geometry_msg *dgm; + struct dm_target_msg *tmsg; + + md = find_device(param); + if (!md) + return -ENXIO; + + /* + * Grab our output buffer. + */ + tmsg = get_result_buffer(param, param_size, &len); + dgm = (struct dm_geometry_msg *)tmsg->message; + + tbl = dm_get_table(md); + + r = dm_table_set_geometry(tbl, &dgm->geo); + + dm_table_put(tbl); + dm_put(md); + + return (r ? 0 : -EINVAL); +} + static int do_suspend(struct dm_ioctl *param) { int r = 0; @@ -1214,7 +1243,8 @@ static ioctl_fn lookup_ioctl(unsigned in {DM_LIST_VERSIONS_CMD, list_versions}, - {DM_TARGET_MSG_CMD, target_message} + {DM_TARGET_MSG_CMD, target_message}, + {DM_DEV_SETGEO_CMD, dev_setgeo} }; return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; diff -Naurp old/drivers/md/dm-table.c linux-2.6.16-rc3/drivers/md/dm-table.c --- old/drivers/md/dm-table.c 2006-02-15 10:49:46.000000000 -0800 +++ linux-2.6.16-rc3/drivers/md/dm-table.c 2006-02-15 10:42:37.000000000 -0800 @@ -15,6 +15,7 @@ #include #include #include +#include #define MAX_DEPTH 16 #define NODE_SIZE L1_CACHE_BYTES @@ -53,6 +54,9 @@ struct dm_table { /* events get handed up using this callback */ void (*event_fn)(void *); void *event_context; + + /* forced geometry settings */ + struct hd_geometry forced_geometry; }; /* @@ -945,6 +949,29 @@ int dm_table_flush_all(struct dm_table * return ret; } +int dm_table_get_geometry(struct dm_table *t, struct hd_geometry *geo) +{ + sector_t sects; + + sects = t->forced_geometry.cylinders * t->forced_geometry.heads + * t->forced_geometry.sectors; + + if (!sects) { + return 0; + } + + memcpy(geo, &t->forced_geometry, sizeof(*geo)); + + return 1; +} + +int dm_table_set_geometry(struct dm_table *t, struct hd_geometry *geo) +{ + memcpy(&t->forced_geometry, geo, sizeof(*geo)); + + return 1; +} + EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); diff -Naurp old/include/linux/dm-ioctl.h linux-2.6.16-rc3/include/linux/dm-ioctl.h --- old/include/linux/dm-ioctl.h 2006-02-15 10:49:47.000000000 -0800 +++ linux-2.6.16-rc3/include/linux/dm-ioctl.h 2006-02-13 18:05:45.000000000 -0800 @@ -9,6 +9,7 @@ #define _LINUX_DM_IOCTL_V4_H #include +#include #define DM_DIR "mapper" /* Slashes not supported */ #define DM_MAX_TYPE_NAME 16 @@ -191,6 +192,11 @@ struct dm_target_msg { char message[0]; }; +/* Used to force a geometry */ +struct dm_geometry_msg { + struct hd_geometry geo; +}; + /* * If you change this make sure you make the corresponding change * to dm-ioctl.c:lookup_ioctl() @@ -218,6 +224,7 @@ enum { /* Added later */ DM_LIST_VERSIONS_CMD, DM_TARGET_MSG_CMD, + DM_DEV_SETGEO_CMD, }; /* @@ -247,6 +254,7 @@ typedef char ioctl_struct[308]; #define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct) #define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct) #define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct) +#define DM_DEV_SETGEO_32 _IOWR(DM_IOCTL, DM_DEV_SETGEO_CMD, ioctl_struct) #endif #define DM_IOCTL 0xfd @@ -270,6 +278,7 @@ typedef char ioctl_struct[308]; #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) +#define DM_DEV_SETGEO _IOWR(DM_IOCTL, DM_DEV_SETGEO_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 #define DM_VERSION_MINOR 5