diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-08 20:21:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-08 20:21:51 -0500 |
commit | 5d0edf29151bb5ba372784b7e369f42cf23a94eb (patch) | |
tree | 847eee159ac3387fd6ad1c385341d70fc45ea13b /drivers/md | |
parent | 4f262acfde22b63498b5e4f165e53d3bb4e96400 (diff) | |
parent | 0ca93de9b789e0eb05e103f0c04de72df13da73a (diff) |
Merge tag 'dm-3.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm
Pull device-mapper fixes for 3.3 from Alasdair Kergon
Eight small device-mapper bug fixes.
* tag 'dm-3.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm:
dm raid: fix flush support
dm raid: set MD_CHANGE_DEVS when rebuilding
dm thin metadata: decrement counter after removing mapped block
dm thin metadata: unlock superblock in init_pmd error path
dm thin metadata: remove incorrect close_device on creation error paths
dm flakey: fix crash on read when corrupt_bio_byte not set
dm io: fix discard support
dm ioctl: do not leak argv if target message only contains whitespace
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-flakey.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-io.c | 23 | ||||
-rw-r--r-- | drivers/md/dm-ioctl.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-raid.c | 17 | ||||
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 25 |
5 files changed, 49 insertions, 20 deletions
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 9fb18c147825..b280c433e4a0 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c | |||
@@ -323,7 +323,7 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, | |||
323 | * Corrupt successful READs while in down state. | 323 | * Corrupt successful READs while in down state. |
324 | * If flags were specified, only corrupt those that match. | 324 | * If flags were specified, only corrupt those that match. |
325 | */ | 325 | */ |
326 | if (!error && bio_submitted_while_down && | 326 | if (fc->corrupt_bio_byte && !error && bio_submitted_while_down && |
327 | (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) && | 327 | (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) && |
328 | all_corrupt_bio_flags_match(bio, fc)) | 328 | all_corrupt_bio_flags_match(bio, fc)) |
329 | corrupt_bio_data(bio, fc); | 329 | corrupt_bio_data(bio, fc); |
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index ad2eba40e319..ea5dd289fe2a 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
@@ -296,6 +296,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
296 | unsigned offset; | 296 | unsigned offset; |
297 | unsigned num_bvecs; | 297 | unsigned num_bvecs; |
298 | sector_t remaining = where->count; | 298 | sector_t remaining = where->count; |
299 | struct request_queue *q = bdev_get_queue(where->bdev); | ||
300 | sector_t discard_sectors; | ||
299 | 301 | ||
300 | /* | 302 | /* |
301 | * where->count may be zero if rw holds a flush and we need to | 303 | * where->count may be zero if rw holds a flush and we need to |
@@ -305,9 +307,12 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
305 | /* | 307 | /* |
306 | * Allocate a suitably sized-bio. | 308 | * Allocate a suitably sized-bio. |
307 | */ | 309 | */ |
308 | num_bvecs = dm_sector_div_up(remaining, | 310 | if (rw & REQ_DISCARD) |
309 | (PAGE_SIZE >> SECTOR_SHIFT)); | 311 | num_bvecs = 1; |
310 | num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); | 312 | else |
313 | num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), | ||
314 | dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT))); | ||
315 | |||
311 | bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); | 316 | bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); |
312 | bio->bi_sector = where->sector + (where->count - remaining); | 317 | bio->bi_sector = where->sector + (where->count - remaining); |
313 | bio->bi_bdev = where->bdev; | 318 | bio->bi_bdev = where->bdev; |
@@ -315,10 +320,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
315 | bio->bi_destructor = dm_bio_destructor; | 320 | bio->bi_destructor = dm_bio_destructor; |
316 | store_io_and_region_in_bio(bio, io, region); | 321 | store_io_and_region_in_bio(bio, io, region); |
317 | 322 | ||
318 | /* | 323 | if (rw & REQ_DISCARD) { |
319 | * Try and add as many pages as possible. | 324 | discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); |
320 | */ | 325 | bio->bi_size = discard_sectors << SECTOR_SHIFT; |
321 | while (remaining) { | 326 | remaining -= discard_sectors; |
327 | } else while (remaining) { | ||
328 | /* | ||
329 | * Try and add as many pages as possible. | ||
330 | */ | ||
322 | dp->get_page(dp, &page, &len, &offset); | 331 | dp->get_page(dp, &page, &len, &offset); |
323 | len = min(len, to_bytes(remaining)); | 332 | len = min(len, to_bytes(remaining)); |
324 | if (!bio_add_page(bio, page, len, offset)) | 333 | if (!bio_add_page(bio, page, len, offset)) |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 31c2dc25886d..1ce84ed0b765 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -1437,7 +1437,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size) | |||
1437 | 1437 | ||
1438 | if (!argc) { | 1438 | if (!argc) { |
1439 | DMWARN("Empty message received."); | 1439 | DMWARN("Empty message received."); |
1440 | goto out; | 1440 | goto out_argv; |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | table = dm_get_live_table(md); | 1443 | table = dm_get_live_table(md); |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 86cb7e5d83d5..787022c18187 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -668,7 +668,14 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev) | |||
668 | return ret; | 668 | return ret; |
669 | 669 | ||
670 | sb = page_address(rdev->sb_page); | 670 | sb = page_address(rdev->sb_page); |
671 | if (sb->magic != cpu_to_le32(DM_RAID_MAGIC)) { | 671 | |
672 | /* | ||
673 | * Two cases that we want to write new superblocks and rebuild: | ||
674 | * 1) New device (no matching magic number) | ||
675 | * 2) Device specified for rebuild (!In_sync w/ offset == 0) | ||
676 | */ | ||
677 | if ((sb->magic != cpu_to_le32(DM_RAID_MAGIC)) || | ||
678 | (!test_bit(In_sync, &rdev->flags) && !rdev->recovery_offset)) { | ||
672 | super_sync(rdev->mddev, rdev); | 679 | super_sync(rdev->mddev, rdev); |
673 | 680 | ||
674 | set_bit(FirstUse, &rdev->flags); | 681 | set_bit(FirstUse, &rdev->flags); |
@@ -745,11 +752,8 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev) | |||
745 | */ | 752 | */ |
746 | rdev_for_each(r, t, mddev) { | 753 | rdev_for_each(r, t, mddev) { |
747 | if (!test_bit(In_sync, &r->flags)) { | 754 | if (!test_bit(In_sync, &r->flags)) { |
748 | if (!test_bit(FirstUse, &r->flags)) | 755 | DMINFO("Device %d specified for rebuild: " |
749 | DMERR("Superblock area of " | 756 | "Clearing superblock", r->raid_disk); |
750 | "rebuild device %d should have been " | ||
751 | "cleared.", r->raid_disk); | ||
752 | set_bit(FirstUse, &r->flags); | ||
753 | rebuilds++; | 757 | rebuilds++; |
754 | } else if (test_bit(FirstUse, &r->flags)) | 758 | } else if (test_bit(FirstUse, &r->flags)) |
755 | new_devs++; | 759 | new_devs++; |
@@ -971,6 +975,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
971 | 975 | ||
972 | INIT_WORK(&rs->md.event_work, do_table_event); | 976 | INIT_WORK(&rs->md.event_work, do_table_event); |
973 | ti->private = rs; | 977 | ti->private = rs; |
978 | ti->num_flush_requests = 1; | ||
974 | 979 | ||
975 | mutex_lock(&rs->md.reconfig_mutex); | 980 | mutex_lock(&rs->md.reconfig_mutex); |
976 | ret = md_run(&rs->md); | 981 | ret = md_run(&rs->md); |
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 59c4f0446ffa..237571af77fd 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -385,6 +385,7 @@ static int init_pmd(struct dm_pool_metadata *pmd, | |||
385 | data_sm = dm_sm_disk_create(tm, nr_blocks); | 385 | data_sm = dm_sm_disk_create(tm, nr_blocks); |
386 | if (IS_ERR(data_sm)) { | 386 | if (IS_ERR(data_sm)) { |
387 | DMERR("sm_disk_create failed"); | 387 | DMERR("sm_disk_create failed"); |
388 | dm_tm_unlock(tm, sblock); | ||
388 | r = PTR_ERR(data_sm); | 389 | r = PTR_ERR(data_sm); |
389 | goto bad; | 390 | goto bad; |
390 | } | 391 | } |
@@ -789,6 +790,11 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) | |||
789 | return 0; | 790 | return 0; |
790 | } | 791 | } |
791 | 792 | ||
793 | /* | ||
794 | * __open_device: Returns @td corresponding to device with id @dev, | ||
795 | * creating it if @create is set and incrementing @td->open_count. | ||
796 | * On failure, @td is undefined. | ||
797 | */ | ||
792 | static int __open_device(struct dm_pool_metadata *pmd, | 798 | static int __open_device(struct dm_pool_metadata *pmd, |
793 | dm_thin_id dev, int create, | 799 | dm_thin_id dev, int create, |
794 | struct dm_thin_device **td) | 800 | struct dm_thin_device **td) |
@@ -799,10 +805,16 @@ static int __open_device(struct dm_pool_metadata *pmd, | |||
799 | struct disk_device_details details_le; | 805 | struct disk_device_details details_le; |
800 | 806 | ||
801 | /* | 807 | /* |
802 | * Check the device isn't already open. | 808 | * If the device is already open, return it. |
803 | */ | 809 | */ |
804 | list_for_each_entry(td2, &pmd->thin_devices, list) | 810 | list_for_each_entry(td2, &pmd->thin_devices, list) |
805 | if (td2->id == dev) { | 811 | if (td2->id == dev) { |
812 | /* | ||
813 | * May not create an already-open device. | ||
814 | */ | ||
815 | if (create) | ||
816 | return -EEXIST; | ||
817 | |||
806 | td2->open_count++; | 818 | td2->open_count++; |
807 | *td = td2; | 819 | *td = td2; |
808 | return 0; | 820 | return 0; |
@@ -817,6 +829,9 @@ static int __open_device(struct dm_pool_metadata *pmd, | |||
817 | if (r != -ENODATA || !create) | 829 | if (r != -ENODATA || !create) |
818 | return r; | 830 | return r; |
819 | 831 | ||
832 | /* | ||
833 | * Create new device. | ||
834 | */ | ||
820 | changed = 1; | 835 | changed = 1; |
821 | details_le.mapped_blocks = 0; | 836 | details_le.mapped_blocks = 0; |
822 | details_le.transaction_id = cpu_to_le64(pmd->trans_id); | 837 | details_le.transaction_id = cpu_to_le64(pmd->trans_id); |
@@ -882,12 +897,10 @@ static int __create_thin(struct dm_pool_metadata *pmd, | |||
882 | 897 | ||
883 | r = __open_device(pmd, dev, 1, &td); | 898 | r = __open_device(pmd, dev, 1, &td); |
884 | if (r) { | 899 | if (r) { |
885 | __close_device(td); | ||
886 | dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); | 900 | dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); |
887 | dm_btree_del(&pmd->bl_info, dev_root); | 901 | dm_btree_del(&pmd->bl_info, dev_root); |
888 | return r; | 902 | return r; |
889 | } | 903 | } |
890 | td->changed = 1; | ||
891 | __close_device(td); | 904 | __close_device(td); |
892 | 905 | ||
893 | return r; | 906 | return r; |
@@ -967,14 +980,14 @@ static int __create_snap(struct dm_pool_metadata *pmd, | |||
967 | goto bad; | 980 | goto bad; |
968 | 981 | ||
969 | r = __set_snapshot_details(pmd, td, origin, pmd->time); | 982 | r = __set_snapshot_details(pmd, td, origin, pmd->time); |
983 | __close_device(td); | ||
984 | |||
970 | if (r) | 985 | if (r) |
971 | goto bad; | 986 | goto bad; |
972 | 987 | ||
973 | __close_device(td); | ||
974 | return 0; | 988 | return 0; |
975 | 989 | ||
976 | bad: | 990 | bad: |
977 | __close_device(td); | ||
978 | dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); | 991 | dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); |
979 | dm_btree_remove(&pmd->details_info, pmd->details_root, | 992 | dm_btree_remove(&pmd->details_info, pmd->details_root, |
980 | &key, &pmd->details_root); | 993 | &key, &pmd->details_root); |
@@ -1211,6 +1224,8 @@ static int __remove(struct dm_thin_device *td, dm_block_t block) | |||
1211 | if (r) | 1224 | if (r) |
1212 | return r; | 1225 | return r; |
1213 | 1226 | ||
1227 | td->mapped_blocks--; | ||
1228 | td->changed = 1; | ||
1214 | pmd->need_commit = 1; | 1229 | pmd->need_commit = 1; |
1215 | 1230 | ||
1216 | return 0; | 1231 | return 0; |