Commit 1f3db25d authored by Mike Snitzer's avatar Mike Snitzer Committed by Alasdair G Kergon

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: default avatarMike Snitzer <snitzer@redhat.com>
Cc: stable@kernel.org
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 1212268f
...@@ -789,6 +789,11 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) ...@@ -789,6 +789,11 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
return 0; return 0;
} }
/*
* __open_device: Returns @td corresponding to device with id @dev,
* creating it if @create is set and incrementing @td->open_count.
* On failure, @td is undefined.
*/
static int __open_device(struct dm_pool_metadata *pmd, static int __open_device(struct dm_pool_metadata *pmd,
dm_thin_id dev, int create, dm_thin_id dev, int create,
struct dm_thin_device **td) struct dm_thin_device **td)
...@@ -799,10 +804,16 @@ static int __open_device(struct dm_pool_metadata *pmd, ...@@ -799,10 +804,16 @@ static int __open_device(struct dm_pool_metadata *pmd,
struct disk_device_details details_le; struct disk_device_details details_le;
/* /*
* Check the device isn't already open. * If the device is already open, return it.
*/ */
list_for_each_entry(td2, &pmd->thin_devices, list) list_for_each_entry(td2, &pmd->thin_devices, list)
if (td2->id == dev) { if (td2->id == dev) {
/*
* May not create an already-open device.
*/
if (create)
return -EEXIST;
td2->open_count++; td2->open_count++;
*td = td2; *td = td2;
return 0; return 0;
...@@ -817,6 +828,9 @@ static int __open_device(struct dm_pool_metadata *pmd, ...@@ -817,6 +828,9 @@ static int __open_device(struct dm_pool_metadata *pmd,
if (r != -ENODATA || !create) if (r != -ENODATA || !create)
return r; return r;
/*
* Create new device.
*/
changed = 1; changed = 1;
details_le.mapped_blocks = 0; details_le.mapped_blocks = 0;
details_le.transaction_id = cpu_to_le64(pmd->trans_id); details_le.transaction_id = cpu_to_le64(pmd->trans_id);
...@@ -882,12 +896,10 @@ static int __create_thin(struct dm_pool_metadata *pmd, ...@@ -882,12 +896,10 @@ static int __create_thin(struct dm_pool_metadata *pmd,
r = __open_device(pmd, dev, 1, &td); r = __open_device(pmd, dev, 1, &td);
if (r) { if (r) {
__close_device(td);
dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
dm_btree_del(&pmd->bl_info, dev_root); dm_btree_del(&pmd->bl_info, dev_root);
return r; return r;
} }
td->changed = 1;
__close_device(td); __close_device(td);
return r; return r;
...@@ -967,14 +979,14 @@ static int __create_snap(struct dm_pool_metadata *pmd, ...@@ -967,14 +979,14 @@ static int __create_snap(struct dm_pool_metadata *pmd,
goto bad; goto bad;
r = __set_snapshot_details(pmd, td, origin, pmd->time); r = __set_snapshot_details(pmd, td, origin, pmd->time);
__close_device(td);
if (r) if (r)
goto bad; goto bad;
__close_device(td);
return 0; return 0;
bad: bad:
__close_device(td);
dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root); dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
dm_btree_remove(&pmd->details_info, pmd->details_root, dm_btree_remove(&pmd->details_info, pmd->details_root,
&key, &pmd->details_root); &key, &pmd->details_root);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment