diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index b99df48cffed..973e63d530ae 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/mempool.h> | 17 | #include <linux/mempool.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/idr.h> | 19 | #include <linux/idr.h> |
20 | #include <linux/hdreg.h> | ||
20 | #include <linux/blktrace_api.h> | 21 | #include <linux/blktrace_api.h> |
21 | 22 | ||
22 | static const char *_name = DM_NAME; | 23 | static const char *_name = DM_NAME; |
@@ -102,6 +103,9 @@ struct mapped_device { | |||
102 | */ | 103 | */ |
103 | struct super_block *frozen_sb; | 104 | struct super_block *frozen_sb; |
104 | struct block_device *suspended_bdev; | 105 | struct block_device *suspended_bdev; |
106 | |||
107 | /* forced geometry settings */ | ||
108 | struct hd_geometry geometry; | ||
105 | }; | 109 | }; |
106 | 110 | ||
107 | #define MIN_IOS 256 | 111 | #define MIN_IOS 256 |
@@ -227,6 +231,13 @@ static int dm_blk_close(struct inode *inode, struct file *file) | |||
227 | return 0; | 231 | return 0; |
228 | } | 232 | } |
229 | 233 | ||
234 | static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
235 | { | ||
236 | struct mapped_device *md = bdev->bd_disk->private_data; | ||
237 | |||
238 | return dm_get_geometry(md, geo); | ||
239 | } | ||
240 | |||
230 | static inline struct dm_io *alloc_io(struct mapped_device *md) | 241 | static inline struct dm_io *alloc_io(struct mapped_device *md) |
231 | { | 242 | { |
232 | return mempool_alloc(md->io_pool, GFP_NOIO); | 243 | return mempool_alloc(md->io_pool, GFP_NOIO); |
@@ -313,6 +324,33 @@ struct dm_table *dm_get_table(struct mapped_device *md) | |||
313 | return t; | 324 | return t; |
314 | } | 325 | } |
315 | 326 | ||
327 | /* | ||
328 | * Get the geometry associated with a dm device | ||
329 | */ | ||
330 | int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo) | ||
331 | { | ||
332 | *geo = md->geometry; | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Set the geometry of a device. | ||
339 | */ | ||
340 | int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo) | ||
341 | { | ||
342 | sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors; | ||
343 | |||
344 | if (geo->start > sz) { | ||
345 | DMWARN("Start sector is beyond the geometry limits."); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | md->geometry = *geo; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
316 | /*----------------------------------------------------------------- | 354 | /*----------------------------------------------------------------- |
317 | * CRUD START: | 355 | * CRUD START: |
318 | * A more elegant soln is in the works that uses the queue | 356 | * A more elegant soln is in the works that uses the queue |
@@ -906,6 +944,13 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
906 | sector_t size; | 944 | sector_t size; |
907 | 945 | ||
908 | size = dm_table_get_size(t); | 946 | size = dm_table_get_size(t); |
947 | |||
948 | /* | ||
949 | * Wipe any geometry if the size of the table changed. | ||
950 | */ | ||
951 | if (size != get_capacity(md->disk)) | ||
952 | memset(&md->geometry, 0, sizeof(md->geometry)); | ||
953 | |||
909 | __set_size(md, size); | 954 | __set_size(md, size); |
910 | if (size == 0) | 955 | if (size == 0) |
911 | return 0; | 956 | return 0; |
@@ -1261,6 +1306,7 @@ int dm_suspended(struct mapped_device *md) | |||
1261 | static struct block_device_operations dm_blk_dops = { | 1306 | static struct block_device_operations dm_blk_dops = { |
1262 | .open = dm_blk_open, | 1307 | .open = dm_blk_open, |
1263 | .release = dm_blk_close, | 1308 | .release = dm_blk_close, |
1309 | .getgeo = dm_blk_getgeo, | ||
1264 | .owner = THIS_MODULE | 1310 | .owner = THIS_MODULE |
1265 | }; | 1311 | }; |
1266 | 1312 | ||