Commit 44d8ebf4 authored by Mike Snitzer's avatar Mike Snitzer

dm thin metadata: use pool locking at end of dm_pool_metadata_close

Ensure that the pool is locked during calls to __commit_transaction and
__destroy_persistent_data_objects.  Just being consistent with locking,
but reality is dm_pool_metadata_close is called once pool is being
destroyed so access to pool shouldn't be contended.

Also, use pmd_write_lock_in_core rather than __pmd_write_lock in
dm_pool_commit_metadata and rename __pmd_write_lock to
pmd_write_lock_in_core -- there was no need for the alias.

In addition, verify that the pool is locked in __commit_transaction().

Fixes: 873f258b ("dm thin metadata: do not write metadata if no changes occurred")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent aa950920
...@@ -387,16 +387,15 @@ static int subtree_equal(void *context, const void *value1_le, const void *value ...@@ -387,16 +387,15 @@ static int subtree_equal(void *context, const void *value1_le, const void *value
* Variant that is used for in-core only changes or code that * Variant that is used for in-core only changes or code that
* shouldn't put the pool in service on its own (e.g. commit). * shouldn't put the pool in service on its own (e.g. commit).
*/ */
static inline void __pmd_write_lock(struct dm_pool_metadata *pmd) static inline void pmd_write_lock_in_core(struct dm_pool_metadata *pmd)
__acquires(pmd->root_lock) __acquires(pmd->root_lock)
{ {
down_write(&pmd->root_lock); down_write(&pmd->root_lock);
} }
#define pmd_write_lock_in_core(pmd) __pmd_write_lock((pmd))
static inline void pmd_write_lock(struct dm_pool_metadata *pmd) static inline void pmd_write_lock(struct dm_pool_metadata *pmd)
{ {
__pmd_write_lock(pmd); pmd_write_lock_in_core(pmd);
if (unlikely(!pmd->in_service)) if (unlikely(!pmd->in_service))
pmd->in_service = true; pmd->in_service = true;
} }
...@@ -831,6 +830,7 @@ static int __commit_transaction(struct dm_pool_metadata *pmd) ...@@ -831,6 +830,7 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
* We need to know if the thin_disk_superblock exceeds a 512-byte sector. * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
*/ */
BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512); BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
BUG_ON(!rwsem_is_locked(&pmd->root_lock));
if (unlikely(!pmd->in_service)) if (unlikely(!pmd->in_service))
return 0; return 0;
...@@ -953,6 +953,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) ...@@ -953,6 +953,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
return -EBUSY; return -EBUSY;
} }
pmd_write_lock_in_core(pmd);
if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) { if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) {
r = __commit_transaction(pmd); r = __commit_transaction(pmd);
if (r < 0) if (r < 0)
...@@ -961,6 +962,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) ...@@ -961,6 +962,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
} }
if (!pmd->fail_io) if (!pmd->fail_io)
__destroy_persistent_data_objects(pmd); __destroy_persistent_data_objects(pmd);
pmd_write_unlock(pmd);
kfree(pmd); kfree(pmd);
return 0; return 0;
...@@ -1841,7 +1843,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) ...@@ -1841,7 +1843,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
* Care is taken to not have commit be what * Care is taken to not have commit be what
* triggers putting the thin-pool in-service. * triggers putting the thin-pool in-service.
*/ */
__pmd_write_lock(pmd); pmd_write_lock_in_core(pmd);
if (pmd->fail_io) if (pmd->fail_io)
goto out; goto out;
......
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