| From fd4c067372e97f1aa1bf3a0a9a23211ac1b476e6 Mon Sep 17 00:00:00 2001 |
| From: Mike Snitzer <snitzer@redhat.com> |
| Date: Mon, 13 Jan 2020 11:18:51 -0500 |
| Subject: [PATCH] dm thin metadata: use pool locking at end of |
| dm_pool_metadata_close |
| |
| commit 44d8ebf436399a40fcd10dd31b29d37823d62fcc upstream. |
| |
| 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: 873f258becca ("dm thin metadata: do not write metadata if no changes occurred") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c |
| index b88d6d701f5b..8bb723f1a569 100644 |
| --- a/drivers/md/dm-thin-metadata.c |
| +++ b/drivers/md/dm-thin-metadata.c |
| @@ -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 |
| * 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) |
| { |
| 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) |
| { |
| - __pmd_write_lock(pmd); |
| + pmd_write_lock_in_core(pmd); |
| if (unlikely(!pmd->in_service)) |
| pmd->in_service = true; |
| } |
| @@ -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. |
| */ |
| BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512); |
| + BUG_ON(!rwsem_is_locked(&pmd->root_lock)); |
| |
| if (unlikely(!pmd->in_service)) |
| return 0; |
| @@ -953,6 +953,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) |
| return -EBUSY; |
| } |
| |
| + pmd_write_lock_in_core(pmd); |
| if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) { |
| r = __commit_transaction(pmd); |
| if (r < 0) |
| @@ -961,6 +962,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) |
| } |
| if (!pmd->fail_io) |
| __destroy_persistent_data_objects(pmd); |
| + pmd_write_unlock(pmd); |
| |
| kfree(pmd); |
| return 0; |
| @@ -1841,7 +1843,7 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) |
| * Care is taken to not have commit be what |
| * triggers putting the thin-pool in-service. |
| */ |
| - __pmd_write_lock(pmd); |
| + pmd_write_lock_in_core(pmd); |
| if (pmd->fail_io) |
| goto out; |
| |
| -- |
| 2.7.4 |
| |