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>
This commit is contained in:
committed by
Alasdair G Kergon
parent
1212268fd9
commit
1f3db25d8b
@@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user