aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2012-03-07 14:09:41 -0500
committerAlasdair G Kergon <agk@redhat.com>2012-03-07 14:09:41 -0500
commit1f3db25d8be4ac50b897b39609802183ea68a514 (patch)
treeb8e140111ba62062d309ae0dec90543f35e28172
parent1212268fd9816e3b8801e57b896fceaec71969ad (diff)
dm thin metadata: remove incorrect close_device on creation error paths
The __open_device() error paths in __create_thin() and __create_snap() incorrectly call __close_device() even if td was not initialized by __open_device(). Remove this. Also document __open_device() return values, remove a redundant td->changed = 1 in __create_thin(), and insert an additional safeguard against creating an already-existing device. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@kernel.org Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-thin-metadata.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 59c4f0446ffa..13d964636d57 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -789,6 +789,11 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
789 return 0; 789 return 0;
790} 790}
791 791
792/*
793 * __open_device: Returns @td corresponding to device with id @dev,
794 * creating it if @create is set and incrementing @td->open_count.
795 * On failure, @td is undefined.
796 */
792static int __open_device(struct dm_pool_metadata *pmd, 797static int __open_device(struct dm_pool_metadata *pmd,
793 dm_thin_id dev, int create, 798 dm_thin_id dev, int create,
794 struct dm_thin_device **td) 799 struct dm_thin_device **td)
@@ -799,10 +804,16 @@ static int __open_device(struct dm_pool_metadata *pmd,
799 struct disk_device_details details_le; 804 struct disk_device_details details_le;
800 805
801 /* 806 /*
802 * Check the device isn't already open. 807 * If the device is already open, return it.
803 */ 808 */
804 list_for_each_entry(td2, &pmd->thin_devices, list) 809 list_for_each_entry(td2, &pmd->thin_devices, list)
805 if (td2->id == dev) { 810 if (td2->id == dev) {
811 /*
812 * May not create an already-open device.
813 */
814 if (create)
815 return -EEXIST;
816
806 td2->open_count++; 817 td2->open_count++;
807 *td = td2; 818 *td = td2;
808 return 0; 819 return 0;
@@ -817,6 +828,9 @@ static int __open_device(struct dm_pool_metadata *pmd,
817 if (r != -ENODATA || !create) 828 if (r != -ENODATA || !create)
818 return r; 829 return r;
819 830
831 /*
832 * Create new device.
833 */
820 changed = 1; 834 changed = 1;
821 details_le.mapped_blocks = 0; 835 details_le.mapped_blocks = 0;
822 details_le.transaction_id = cpu_to_le64(pmd->trans_id); 836 details_le.transaction_id = cpu_to_le64(pmd->trans_id);
@@ -882,12 +896,10 @@ static int __create_thin(struct dm_pool_metadata *pmd,
882 896
883 r = __open_device(pmd, dev, 1, &td); 897 r = __open_device(pmd, dev, 1, &td);
884 if (r) { 898 if (r) {
885 __close_device(td);
886 dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); 899 dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
887 dm_btree_del(&pmd->bl_info, dev_root); 900 dm_btree_del(&pmd->bl_info, dev_root);
888 return r; 901 return r;
889 } 902 }
890 td->changed = 1;
891 __close_device(td); 903 __close_device(td);
892 904
893 return r; 905 return r;
@@ -967,14 +979,14 @@ static int __create_snap(struct dm_pool_metadata *pmd,
967 goto bad; 979 goto bad;
968 980
969 r = __set_snapshot_details(pmd, td, origin, pmd->time); 981 r = __set_snapshot_details(pmd, td, origin, pmd->time);
982 __close_device(td);
983
970 if (r) 984 if (r)
971 goto bad; 985 goto bad;
972 986
973 __close_device(td);
974 return 0; 987 return 0;
975 988
976bad: 989bad:
977 __close_device(td);
978 dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); 990 dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
979 dm_btree_remove(&pmd->details_info, pmd->details_root, 991 dm_btree_remove(&pmd->details_info, pmd->details_root,
980 &key, &pmd->details_root); 992 &key, &pmd->details_root);