diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-25 23:51:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-25 23:51:44 -0400 |
| commit | 44bbd7ac2658eb1118342493026ef141e259b739 (patch) | |
| tree | a804d3503e48ee8b2bd0dd3c40235e482a75a512 | |
| parent | 24c6d02fe8c34bc958aa4c464efc1cc10d43e29d (diff) | |
| parent | 29915202006c2e7bafe81348eb498ff9a724ac61 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm
* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm:
dm stripe: implement merge method
dm mpath: allow table load with no priority groups
dm mpath: fail message ioctl if specified path is not valid
dm ioctl: add flag to wipe buffers for secure data
dm ioctl: prepare for crypt key wiping
dm crypt: wipe keys string immediately after key is set
dm: add flakey target
dm: fix opening log and cow devices for read only tables
| -rw-r--r-- | Documentation/device-mapper/dm-flakey.txt | 17 | ||||
| -rw-r--r-- | drivers/md/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/md/Makefile | 1 | ||||
| -rw-r--r-- | drivers/md/dm-crypt.c | 19 | ||||
| -rw-r--r-- | drivers/md/dm-flakey.c | 212 | ||||
| -rw-r--r-- | drivers/md/dm-ioctl.c | 46 | ||||
| -rw-r--r-- | drivers/md/dm-log.c | 2 | ||||
| -rw-r--r-- | drivers/md/dm-mpath.c | 17 | ||||
| -rw-r--r-- | drivers/md/dm-snap.c | 2 | ||||
| -rw-r--r-- | drivers/md/dm-stripe.c | 23 | ||||
| -rw-r--r-- | include/linux/dm-ioctl.h | 12 |
11 files changed, 326 insertions, 31 deletions
diff --git a/Documentation/device-mapper/dm-flakey.txt b/Documentation/device-mapper/dm-flakey.txt new file mode 100644 index 000000000000..c8efdfd19a65 --- /dev/null +++ b/Documentation/device-mapper/dm-flakey.txt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | dm-flakey | ||
| 2 | ========= | ||
| 3 | |||
| 4 | This target is the same as the linear target except that it returns I/O | ||
| 5 | errors periodically. It's been found useful in simulating failing | ||
| 6 | devices for testing purposes. | ||
| 7 | |||
| 8 | Starting from the time the table is loaded, the device is available for | ||
| 9 | <up interval> seconds, then returns errors for <down interval> seconds, | ||
| 10 | and then this cycle repeats. | ||
| 11 | |||
| 12 | Parameters: <dev path> <offset> <up interval> <down interval> | ||
| 13 | <dev path>: Full pathname to the underlying block-device, or a | ||
| 14 | "major:minor" device-number. | ||
| 15 | <offset>: Starting sector within the device. | ||
| 16 | <up interval>: Number of seconds device is available. | ||
| 17 | <down interval>: Number of seconds device returns errors. | ||
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 98d9ec85e0eb..8420129fc5ee 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
| @@ -327,4 +327,10 @@ config DM_UEVENT | |||
| 327 | ---help--- | 327 | ---help--- |
| 328 | Generate udev events for DM events. | 328 | Generate udev events for DM events. |
| 329 | 329 | ||
| 330 | config DM_FLAKEY | ||
| 331 | tristate "Flakey target (EXPERIMENTAL)" | ||
| 332 | depends on BLK_DEV_DM && EXPERIMENTAL | ||
| 333 | ---help--- | ||
| 334 | A target that intermittently fails I/O for debugging purposes. | ||
| 335 | |||
| 330 | endif # MD | 336 | endif # MD |
diff --git a/drivers/md/Makefile b/drivers/md/Makefile index d0138606c2e8..448838b1f92a 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_BLK_DEV_MD) += md-mod.o | |||
| 29 | obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o | 29 | obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o |
| 30 | obj-$(CONFIG_DM_CRYPT) += dm-crypt.o | 30 | obj-$(CONFIG_DM_CRYPT) += dm-crypt.o |
| 31 | obj-$(CONFIG_DM_DELAY) += dm-delay.o | 31 | obj-$(CONFIG_DM_DELAY) += dm-delay.o |
| 32 | obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o | ||
| 32 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o | 33 | obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o |
| 33 | obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o | 34 | obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o |
| 34 | obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o | 35 | obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 2c62c1169f78..c8827ffd85bb 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -1324,20 +1324,29 @@ static int crypt_setkey_allcpus(struct crypt_config *cc) | |||
| 1324 | 1324 | ||
| 1325 | static int crypt_set_key(struct crypt_config *cc, char *key) | 1325 | static int crypt_set_key(struct crypt_config *cc, char *key) |
| 1326 | { | 1326 | { |
| 1327 | int r = -EINVAL; | ||
| 1328 | int key_string_len = strlen(key); | ||
| 1329 | |||
| 1327 | /* The key size may not be changed. */ | 1330 | /* The key size may not be changed. */ |
| 1328 | if (cc->key_size != (strlen(key) >> 1)) | 1331 | if (cc->key_size != (key_string_len >> 1)) |
| 1329 | return -EINVAL; | 1332 | goto out; |
| 1330 | 1333 | ||
| 1331 | /* Hyphen (which gives a key_size of zero) means there is no key. */ | 1334 | /* Hyphen (which gives a key_size of zero) means there is no key. */ |
| 1332 | if (!cc->key_size && strcmp(key, "-")) | 1335 | if (!cc->key_size && strcmp(key, "-")) |
| 1333 | return -EINVAL; | 1336 | goto out; |
| 1334 | 1337 | ||
| 1335 | if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0) | 1338 | if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0) |
| 1336 | return -EINVAL; | 1339 | goto out; |
| 1337 | 1340 | ||
| 1338 | set_bit(DM_CRYPT_KEY_VALID, &cc->flags); | 1341 | set_bit(DM_CRYPT_KEY_VALID, &cc->flags); |
| 1339 | 1342 | ||
| 1340 | return crypt_setkey_allcpus(cc); | 1343 | r = crypt_setkey_allcpus(cc); |
| 1344 | |||
| 1345 | out: | ||
| 1346 | /* Hex key string not needed after here, so wipe it. */ | ||
| 1347 | memset(key, '0', key_string_len); | ||
| 1348 | |||
| 1349 | return r; | ||
| 1341 | } | 1350 | } |
| 1342 | 1351 | ||
| 1343 | static int crypt_wipe_key(struct crypt_config *cc) | 1352 | static int crypt_wipe_key(struct crypt_config *cc) |
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c new file mode 100644 index 000000000000..ea790623c30b --- /dev/null +++ b/drivers/md/dm-flakey.c | |||
| @@ -0,0 +1,212 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2003 Sistina Software (UK) Limited. | ||
| 3 | * Copyright (C) 2004, 2010 Red Hat, Inc. All rights reserved. | ||
| 4 | * | ||
| 5 | * This file is released under the GPL. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/device-mapper.h> | ||
| 9 | |||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/blkdev.h> | ||
| 13 | #include <linux/bio.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | |||
| 16 | #define DM_MSG_PREFIX "flakey" | ||
| 17 | |||
| 18 | /* | ||
| 19 | * Flakey: Used for testing only, simulates intermittent, | ||
| 20 | * catastrophic device failure. | ||
| 21 | */ | ||
| 22 | struct flakey_c { | ||
| 23 | struct dm_dev *dev; | ||
| 24 | unsigned long start_time; | ||
| 25 | sector_t start; | ||
| 26 | unsigned up_interval; | ||
| 27 | unsigned down_interval; | ||
| 28 | }; | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Construct a flakey mapping: <dev_path> <offset> <up interval> <down interval> | ||
| 32 | */ | ||
| 33 | static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) | ||
| 34 | { | ||
| 35 | struct flakey_c *fc; | ||
| 36 | unsigned long long tmp; | ||
| 37 | |||
| 38 | if (argc != 4) { | ||
| 39 | ti->error = "dm-flakey: Invalid argument count"; | ||
| 40 | return -EINVAL; | ||
| 41 | } | ||
| 42 | |||
| 43 | fc = kmalloc(sizeof(*fc), GFP_KERNEL); | ||
| 44 | if (!fc) { | ||
| 45 | ti->error = "dm-flakey: Cannot allocate linear context"; | ||
| 46 | return -ENOMEM; | ||
| 47 | } | ||
| 48 | fc->start_time = jiffies; | ||
| 49 | |||
| 50 | if (sscanf(argv[1], "%llu", &tmp) != 1) { | ||
| 51 | ti->error = "dm-flakey: Invalid device sector"; | ||
| 52 | goto bad; | ||
| 53 | } | ||
| 54 | fc->start = tmp; | ||
| 55 | |||
| 56 | if (sscanf(argv[2], "%u", &fc->up_interval) != 1) { | ||
| 57 | ti->error = "dm-flakey: Invalid up interval"; | ||
| 58 | goto bad; | ||
| 59 | } | ||
| 60 | |||
| 61 | if (sscanf(argv[3], "%u", &fc->down_interval) != 1) { | ||
| 62 | ti->error = "dm-flakey: Invalid down interval"; | ||
| 63 | goto bad; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (!(fc->up_interval + fc->down_interval)) { | ||
| 67 | ti->error = "dm-flakey: Total (up + down) interval is zero"; | ||
| 68 | goto bad; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (fc->up_interval + fc->down_interval < fc->up_interval) { | ||
| 72 | ti->error = "dm-flakey: Interval overflow"; | ||
| 73 | goto bad; | ||
| 74 | } | ||
| 75 | |||
| 76 | if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &fc->dev)) { | ||
| 77 | ti->error = "dm-flakey: Device lookup failed"; | ||
| 78 | goto bad; | ||
| 79 | } | ||
| 80 | |||
| 81 | ti->num_flush_requests = 1; | ||
| 82 | ti->private = fc; | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | bad: | ||
| 86 | kfree(fc); | ||
| 87 | return -EINVAL; | ||
| 88 | } | ||
| 89 | |||
| 90 | static void flakey_dtr(struct dm_target *ti) | ||
| 91 | { | ||
| 92 | struct flakey_c *fc = ti->private; | ||
| 93 | |||
| 94 | dm_put_device(ti, fc->dev); | ||
| 95 | kfree(fc); | ||
| 96 | } | ||
| 97 | |||
| 98 | static sector_t flakey_map_sector(struct dm_target *ti, sector_t bi_sector) | ||
| 99 | { | ||
| 100 | struct flakey_c *fc = ti->private; | ||
| 101 | |||
| 102 | return fc->start + (bi_sector - ti->begin); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void flakey_map_bio(struct dm_target *ti, struct bio *bio) | ||
| 106 | { | ||
| 107 | struct flakey_c *fc = ti->private; | ||
| 108 | |||
| 109 | bio->bi_bdev = fc->dev->bdev; | ||
| 110 | if (bio_sectors(bio)) | ||
| 111 | bio->bi_sector = flakey_map_sector(ti, bio->bi_sector); | ||
| 112 | } | ||
| 113 | |||
| 114 | static int flakey_map(struct dm_target *ti, struct bio *bio, | ||
| 115 | union map_info *map_context) | ||
| 116 | { | ||
| 117 | struct flakey_c *fc = ti->private; | ||
| 118 | unsigned elapsed; | ||
| 119 | |||
| 120 | /* Are we alive ? */ | ||
| 121 | elapsed = (jiffies - fc->start_time) / HZ; | ||
| 122 | if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) | ||
| 123 | return -EIO; | ||
| 124 | |||
| 125 | flakey_map_bio(ti, bio); | ||
| 126 | |||
| 127 | return DM_MAPIO_REMAPPED; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int flakey_status(struct dm_target *ti, status_type_t type, | ||
| 131 | char *result, unsigned int maxlen) | ||
| 132 | { | ||
| 133 | struct flakey_c *fc = ti->private; | ||
| 134 | |||
| 135 | switch (type) { | ||
| 136 | case STATUSTYPE_INFO: | ||
| 137 | result[0] = '\0'; | ||
| 138 | break; | ||
| 139 | |||
| 140 | case STATUSTYPE_TABLE: | ||
| 141 | snprintf(result, maxlen, "%s %llu %u %u", fc->dev->name, | ||
| 142 | (unsigned long long)fc->start, fc->up_interval, | ||
| 143 | fc->down_interval); | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) | ||
| 150 | { | ||
| 151 | struct flakey_c *fc = ti->private; | ||
| 152 | |||
| 153 | return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg); | ||
| 154 | } | ||
| 155 | |||
| 156 | static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | ||
| 157 | struct bio_vec *biovec, int max_size) | ||
| 158 | { | ||
| 159 | struct flakey_c *fc = ti->private; | ||
| 160 | struct request_queue *q = bdev_get_queue(fc->dev->bdev); | ||
| 161 | |||
| 162 | if (!q->merge_bvec_fn) | ||
| 163 | return max_size; | ||
| 164 | |||
| 165 | bvm->bi_bdev = fc->dev->bdev; | ||
| 166 | bvm->bi_sector = flakey_map_sector(ti, bvm->bi_sector); | ||
| 167 | |||
| 168 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) | ||
| 172 | { | ||
| 173 | struct flakey_c *fc = ti->private; | ||
| 174 | |||
| 175 | return fn(ti, fc->dev, fc->start, ti->len, data); | ||
| 176 | } | ||
| 177 | |||
| 178 | static struct target_type flakey_target = { | ||
| 179 | .name = "flakey", | ||
| 180 | .version = {1, 1, 0}, | ||
| 181 | .module = THIS_MODULE, | ||
| 182 | .ctr = flakey_ctr, | ||
| 183 | .dtr = flakey_dtr, | ||
| 184 | .map = flakey_map, | ||
| 185 | .status = flakey_status, | ||
| 186 | .ioctl = flakey_ioctl, | ||
| 187 | .merge = flakey_merge, | ||
| 188 | .iterate_devices = flakey_iterate_devices, | ||
| 189 | }; | ||
| 190 | |||
| 191 | static int __init dm_flakey_init(void) | ||
| 192 | { | ||
| 193 | int r = dm_register_target(&flakey_target); | ||
| 194 | |||
| 195 | if (r < 0) | ||
| 196 | DMERR("register failed %d", r); | ||
| 197 | |||
| 198 | return r; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void __exit dm_flakey_exit(void) | ||
| 202 | { | ||
| 203 | dm_unregister_target(&flakey_target); | ||
| 204 | } | ||
| 205 | |||
| 206 | /* Module hooks */ | ||
| 207 | module_init(dm_flakey_init); | ||
| 208 | module_exit(dm_flakey_exit); | ||
| 209 | |||
| 210 | MODULE_DESCRIPTION(DM_NAME " flakey target"); | ||
| 211 | MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); | ||
| 212 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 6d12775a1061..4cacdad2270a 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
| @@ -1501,14 +1501,10 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user) | |||
| 1501 | return r; | 1501 | return r; |
| 1502 | } | 1502 | } |
| 1503 | 1503 | ||
| 1504 | static void free_params(struct dm_ioctl *param) | ||
| 1505 | { | ||
| 1506 | vfree(param); | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | 1504 | static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) |
| 1510 | { | 1505 | { |
| 1511 | struct dm_ioctl tmp, *dmi; | 1506 | struct dm_ioctl tmp, *dmi; |
| 1507 | int secure_data; | ||
| 1512 | 1508 | ||
| 1513 | if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data))) | 1509 | if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data))) |
| 1514 | return -EFAULT; | 1510 | return -EFAULT; |
| @@ -1516,17 +1512,30 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | |||
| 1516 | if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data))) | 1512 | if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data))) |
| 1517 | return -EINVAL; | 1513 | return -EINVAL; |
| 1518 | 1514 | ||
| 1515 | secure_data = tmp.flags & DM_SECURE_DATA_FLAG; | ||
| 1516 | |||
| 1519 | dmi = vmalloc(tmp.data_size); | 1517 | dmi = vmalloc(tmp.data_size); |
| 1520 | if (!dmi) | 1518 | if (!dmi) { |
| 1519 | if (secure_data && clear_user(user, tmp.data_size)) | ||
| 1520 | return -EFAULT; | ||
| 1521 | return -ENOMEM; | 1521 | return -ENOMEM; |
| 1522 | |||
| 1523 | if (copy_from_user(dmi, user, tmp.data_size)) { | ||
| 1524 | vfree(dmi); | ||
| 1525 | return -EFAULT; | ||
| 1526 | } | 1522 | } |
| 1527 | 1523 | ||
| 1524 | if (copy_from_user(dmi, user, tmp.data_size)) | ||
| 1525 | goto bad; | ||
| 1526 | |||
| 1527 | /* Wipe the user buffer so we do not return it to userspace */ | ||
| 1528 | if (secure_data && clear_user(user, tmp.data_size)) | ||
| 1529 | goto bad; | ||
| 1530 | |||
| 1528 | *param = dmi; | 1531 | *param = dmi; |
| 1529 | return 0; | 1532 | return 0; |
| 1533 | |||
| 1534 | bad: | ||
| 1535 | if (secure_data) | ||
| 1536 | memset(dmi, 0, tmp.data_size); | ||
| 1537 | vfree(dmi); | ||
| 1538 | return -EFAULT; | ||
| 1530 | } | 1539 | } |
| 1531 | 1540 | ||
| 1532 | static int validate_params(uint cmd, struct dm_ioctl *param) | 1541 | static int validate_params(uint cmd, struct dm_ioctl *param) |
| @@ -1534,6 +1543,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) | |||
| 1534 | /* Always clear this flag */ | 1543 | /* Always clear this flag */ |
| 1535 | param->flags &= ~DM_BUFFER_FULL_FLAG; | 1544 | param->flags &= ~DM_BUFFER_FULL_FLAG; |
| 1536 | param->flags &= ~DM_UEVENT_GENERATED_FLAG; | 1545 | param->flags &= ~DM_UEVENT_GENERATED_FLAG; |
| 1546 | param->flags &= ~DM_SECURE_DATA_FLAG; | ||
| 1537 | 1547 | ||
| 1538 | /* Ignores parameters */ | 1548 | /* Ignores parameters */ |
| 1539 | if (cmd == DM_REMOVE_ALL_CMD || | 1549 | if (cmd == DM_REMOVE_ALL_CMD || |
| @@ -1561,10 +1571,11 @@ static int validate_params(uint cmd, struct dm_ioctl *param) | |||
| 1561 | static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | 1571 | static int ctl_ioctl(uint command, struct dm_ioctl __user *user) |
| 1562 | { | 1572 | { |
| 1563 | int r = 0; | 1573 | int r = 0; |
| 1574 | int wipe_buffer; | ||
| 1564 | unsigned int cmd; | 1575 | unsigned int cmd; |
| 1565 | struct dm_ioctl *uninitialized_var(param); | 1576 | struct dm_ioctl *uninitialized_var(param); |
| 1566 | ioctl_fn fn = NULL; | 1577 | ioctl_fn fn = NULL; |
| 1567 | size_t param_size; | 1578 | size_t input_param_size; |
| 1568 | 1579 | ||
| 1569 | /* only root can play with this */ | 1580 | /* only root can play with this */ |
| 1570 | if (!capable(CAP_SYS_ADMIN)) | 1581 | if (!capable(CAP_SYS_ADMIN)) |
| @@ -1611,13 +1622,15 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | |||
| 1611 | if (r) | 1622 | if (r) |
| 1612 | return r; | 1623 | return r; |
| 1613 | 1624 | ||
| 1625 | input_param_size = param->data_size; | ||
| 1626 | wipe_buffer = param->flags & DM_SECURE_DATA_FLAG; | ||
| 1627 | |||
| 1614 | r = validate_params(cmd, param); | 1628 | r = validate_params(cmd, param); |
| 1615 | if (r) | 1629 | if (r) |
| 1616 | goto out; | 1630 | goto out; |
| 1617 | 1631 | ||
| 1618 | param_size = param->data_size; | ||
| 1619 | param->data_size = sizeof(*param); | 1632 | param->data_size = sizeof(*param); |
| 1620 | r = fn(param, param_size); | 1633 | r = fn(param, input_param_size); |
| 1621 | 1634 | ||
| 1622 | /* | 1635 | /* |
| 1623 | * Copy the results back to userland. | 1636 | * Copy the results back to userland. |
| @@ -1625,8 +1638,11 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | |||
| 1625 | if (!r && copy_to_user(user, param, param->data_size)) | 1638 | if (!r && copy_to_user(user, param, param->data_size)) |
| 1626 | r = -EFAULT; | 1639 | r = -EFAULT; |
| 1627 | 1640 | ||
| 1628 | out: | 1641 | out: |
| 1629 | free_params(param); | 1642 | if (wipe_buffer) |
| 1643 | memset(param, 0, input_param_size); | ||
| 1644 | |||
| 1645 | vfree(param); | ||
| 1630 | return r; | 1646 | return r; |
| 1631 | } | 1647 | } |
| 1632 | 1648 | ||
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 57968eb382c1..a1f321889676 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
| @@ -543,7 +543,7 @@ static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti, | |||
| 543 | return -EINVAL; | 543 | return -EINVAL; |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &dev); | 546 | r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev); |
| 547 | if (r) | 547 | if (r) |
| 548 | return r; | 548 | return r; |
| 549 | 549 | ||
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 4b0b63c290a6..a550a057d991 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
| @@ -844,8 +844,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
| 844 | { | 844 | { |
| 845 | /* target parameters */ | 845 | /* target parameters */ |
| 846 | static struct param _params[] = { | 846 | static struct param _params[] = { |
| 847 | {1, 1024, "invalid number of priority groups"}, | 847 | {0, 1024, "invalid number of priority groups"}, |
| 848 | {1, 1024, "invalid initial priority group number"}, | 848 | {0, 1024, "invalid initial priority group number"}, |
| 849 | }; | 849 | }; |
| 850 | 850 | ||
| 851 | int r; | 851 | int r; |
| @@ -879,6 +879,13 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
| 879 | if (r) | 879 | if (r) |
| 880 | goto bad; | 880 | goto bad; |
| 881 | 881 | ||
| 882 | if ((!m->nr_priority_groups && next_pg_num) || | ||
| 883 | (m->nr_priority_groups && !next_pg_num)) { | ||
| 884 | ti->error = "invalid initial priority group"; | ||
| 885 | r = -EINVAL; | ||
| 886 | goto bad; | ||
| 887 | } | ||
| 888 | |||
| 882 | /* parse the priority groups */ | 889 | /* parse the priority groups */ |
| 883 | while (as.argc) { | 890 | while (as.argc) { |
| 884 | struct priority_group *pg; | 891 | struct priority_group *pg; |
| @@ -1065,7 +1072,7 @@ out: | |||
| 1065 | static int action_dev(struct multipath *m, struct dm_dev *dev, | 1072 | static int action_dev(struct multipath *m, struct dm_dev *dev, |
| 1066 | action_fn action) | 1073 | action_fn action) |
| 1067 | { | 1074 | { |
| 1068 | int r = 0; | 1075 | int r = -EINVAL; |
| 1069 | struct pgpath *pgpath; | 1076 | struct pgpath *pgpath; |
| 1070 | struct priority_group *pg; | 1077 | struct priority_group *pg; |
| 1071 | 1078 | ||
| @@ -1415,7 +1422,7 @@ static int multipath_status(struct dm_target *ti, status_type_t type, | |||
| 1415 | else if (m->current_pg) | 1422 | else if (m->current_pg) |
| 1416 | pg_num = m->current_pg->pg_num; | 1423 | pg_num = m->current_pg->pg_num; |
| 1417 | else | 1424 | else |
| 1418 | pg_num = 1; | 1425 | pg_num = (m->nr_priority_groups ? 1 : 0); |
| 1419 | 1426 | ||
| 1420 | DMEMIT("%u ", pg_num); | 1427 | DMEMIT("%u ", pg_num); |
| 1421 | 1428 | ||
| @@ -1669,7 +1676,7 @@ out: | |||
| 1669 | *---------------------------------------------------------------*/ | 1676 | *---------------------------------------------------------------*/ |
| 1670 | static struct target_type multipath_target = { | 1677 | static struct target_type multipath_target = { |
| 1671 | .name = "multipath", | 1678 | .name = "multipath", |
| 1672 | .version = {1, 2, 0}, | 1679 | .version = {1, 3, 0}, |
| 1673 | .module = THIS_MODULE, | 1680 | .module = THIS_MODULE, |
| 1674 | .ctr = multipath_ctr, | 1681 | .ctr = multipath_ctr, |
| 1675 | .dtr = multipath_dtr, | 1682 | .dtr = multipath_dtr, |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index fdde53cd12b7..a2d330942cb2 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -1080,7 +1080,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1080 | argv++; | 1080 | argv++; |
| 1081 | argc--; | 1081 | argc--; |
| 1082 | 1082 | ||
| 1083 | r = dm_get_device(ti, cow_path, FMODE_READ | FMODE_WRITE, &s->cow); | 1083 | r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); |
| 1084 | if (r) { | 1084 | if (r) { |
| 1085 | ti->error = "Cannot get COW device"; | 1085 | ti->error = "Cannot get COW device"; |
| 1086 | goto bad_cow; | 1086 | goto bad_cow; |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index dddfa14f2982..3d80cf0c152d 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
| @@ -396,9 +396,29 @@ static void stripe_io_hints(struct dm_target *ti, | |||
| 396 | blk_limits_io_opt(limits, chunk_size * sc->stripes); | 396 | blk_limits_io_opt(limits, chunk_size * sc->stripes); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | ||
| 400 | struct bio_vec *biovec, int max_size) | ||
| 401 | { | ||
| 402 | struct stripe_c *sc = ti->private; | ||
| 403 | sector_t bvm_sector = bvm->bi_sector; | ||
| 404 | uint32_t stripe; | ||
| 405 | struct request_queue *q; | ||
| 406 | |||
| 407 | stripe_map_sector(sc, bvm_sector, &stripe, &bvm_sector); | ||
| 408 | |||
| 409 | q = bdev_get_queue(sc->stripe[stripe].dev->bdev); | ||
| 410 | if (!q->merge_bvec_fn) | ||
| 411 | return max_size; | ||
| 412 | |||
| 413 | bvm->bi_bdev = sc->stripe[stripe].dev->bdev; | ||
| 414 | bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector; | ||
| 415 | |||
| 416 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | ||
| 417 | } | ||
| 418 | |||
| 399 | static struct target_type stripe_target = { | 419 | static struct target_type stripe_target = { |
| 400 | .name = "striped", | 420 | .name = "striped", |
| 401 | .version = {1, 3, 1}, | 421 | .version = {1, 4, 0}, |
| 402 | .module = THIS_MODULE, | 422 | .module = THIS_MODULE, |
| 403 | .ctr = stripe_ctr, | 423 | .ctr = stripe_ctr, |
| 404 | .dtr = stripe_dtr, | 424 | .dtr = stripe_dtr, |
| @@ -407,6 +427,7 @@ static struct target_type stripe_target = { | |||
| 407 | .status = stripe_status, | 427 | .status = stripe_status, |
| 408 | .iterate_devices = stripe_iterate_devices, | 428 | .iterate_devices = stripe_iterate_devices, |
| 409 | .io_hints = stripe_io_hints, | 429 | .io_hints = stripe_io_hints, |
| 430 | .merge = stripe_merge, | ||
| 410 | }; | 431 | }; |
| 411 | 432 | ||
| 412 | int __init dm_stripe_init(void) | 433 | int __init dm_stripe_init(void) |
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 78bbf47bbb96..3708455ee6c3 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h | |||
| @@ -267,9 +267,9 @@ enum { | |||
| 267 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | 267 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) |
| 268 | 268 | ||
| 269 | #define DM_VERSION_MAJOR 4 | 269 | #define DM_VERSION_MAJOR 4 |
| 270 | #define DM_VERSION_MINOR 19 | 270 | #define DM_VERSION_MINOR 20 |
| 271 | #define DM_VERSION_PATCHLEVEL 1 | 271 | #define DM_VERSION_PATCHLEVEL 0 |
| 272 | #define DM_VERSION_EXTRA "-ioctl (2011-01-07)" | 272 | #define DM_VERSION_EXTRA "-ioctl (2011-02-02)" |
| 273 | 273 | ||
| 274 | /* Status bits */ | 274 | /* Status bits */ |
| 275 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ | 275 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |
| @@ -328,4 +328,10 @@ enum { | |||
| 328 | */ | 328 | */ |
| 329 | #define DM_UUID_FLAG (1 << 14) /* In */ | 329 | #define DM_UUID_FLAG (1 << 14) /* In */ |
| 330 | 330 | ||
| 331 | /* | ||
| 332 | * If set, all buffers are wiped after use. Use when sending | ||
| 333 | * or requesting sensitive data such as an encryption key. | ||
| 334 | */ | ||
| 335 | #define DM_SECURE_DATA_FLAG (1 << 15) /* In */ | ||
| 336 | |||
| 331 | #endif /* _LINUX_DM_IOCTL_H */ | 337 | #endif /* _LINUX_DM_IOCTL_H */ |
