--- drivers/md/dm-thin-metadata.c | 137 ++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 62 deletions(-) Index: linux-3.0/drivers/md/dm-thin-metadata.c =================================================================== --- linux-3.0.orig/drivers/md/dm-thin-metadata.c +++ linux-3.0/drivers/md/dm-thin-metadata.c @@ -497,7 +497,7 @@ bad: return ERR_PTR(r); } -static int begin_transaction(struct dm_pool_metadata *pmd) +static int __begin_transaction(struct dm_pool_metadata *pmd) { int r; u32 features; @@ -507,7 +507,6 @@ static int begin_transaction(struct dm_p * dm_pool_commit_metadata() resets pmd->sblock */ WARN_ON(pmd->sblock); - pmd->need_commit = 0; /* * superblock is unlocked via dm_tm_commit() @@ -581,7 +580,7 @@ struct dm_pool_metadata *dm_pool_metadat pmd->bdev = bdev; if (!create) { - r = begin_transaction(pmd); + r = __begin_transaction(pmd); if (r < 0) goto bad; return pmd; @@ -591,7 +590,7 @@ struct dm_pool_metadata *dm_pool_metadat * Create. */ if (!pmd->sblock) { - r = begin_transaction(pmd); + r = __begin_transaction(pmd); if (r < 0) goto bad; } @@ -631,46 +630,6 @@ bad: return ERR_PTR(r); } -int dm_pool_metadata_close(struct dm_pool_metadata *pmd) -{ - int r; - unsigned open_devices = 0; - struct dm_thin_device *td, *tmp; - - down_read(&pmd->root_lock); - list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) { - if (td->open_count) - open_devices++; - else { - list_del(&td->list); - kfree(td); - } - } - up_read(&pmd->root_lock); - - if (open_devices) { - DMERR("attempt to close pmd when %u device(s) are still open", - open_devices); - return -EBUSY; - } - - if (pmd->sblock) { - r = dm_pool_commit_metadata(pmd); - if (r) - DMWARN("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - } - - dm_tm_destroy(pmd->tm); - dm_tm_destroy(pmd->nb_tm); - dm_block_manager_destroy(pmd->bm); - dm_sm_destroy(pmd->metadata_sm); - dm_sm_destroy(pmd->data_sm); - kfree(pmd); - - return 0; -} - int dm_pool_rebind_metadata_device(struct dm_pool_metadata *pmd, struct block_device *bdev) { @@ -1193,36 +1152,30 @@ static int __write_changed_details(struc return 0; } -int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) +static int __commit_metadata(struct dm_pool_metadata *pmd) { /* - * FIXME: associated pool should be made read-only on + * FIXME: Associated pool should be made read-only on * dm_pool_commit_metadata failure. */ int r; size_t len; struct thin_disk_superblock *disk_super; - /* - * We need to know if the thin_disk_superblock exceeds a 512-byte sector. - */ - BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512); - - down_write(&pmd->root_lock); r = __write_changed_details(pmd); if (r < 0) - goto out; + return r; if (!pmd->need_commit) - goto out; + return r; r = dm_tm_pre_commit(pmd->tm); if (r < 0) - goto out; + return r; r = dm_sm_root_size(pmd->metadata_sm, &len); if (r < 0) - goto out; + return r; disk_super = dm_block_data(pmd->sblock); disk_super->time = cpu_to_le32(pmd->time); @@ -1233,27 +1186,87 @@ int dm_pool_commit_metadata(struct dm_po r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root, len); if (r < 0) - goto out; + return r; r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root, len); if (r < 0) - goto out; + return r; r = dm_tm_commit(pmd->tm, pmd->sblock); - if (r < 0) + + pmd->sblock = NULL; + pmd->need_commit = 0; + + return r; +} + +int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) +{ + int r; + + /* + * We need to know if the thin_disk_superblock exceeds a 512-byte sector. + */ + BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512); + + down_write(&pmd->root_lock); + + r = __commit_metadata(pmd); + if (r) goto out; /* * Open the next transaction. */ - pmd->sblock = NULL; - - r = begin_transaction(pmd); + r = __begin_transaction(pmd); out: up_write(&pmd->root_lock); + return r; } +int dm_pool_metadata_close(struct dm_pool_metadata *pmd) +{ + int r; + unsigned open_devices = 0; + struct dm_thin_device *td, *tmp; + + down_read(&pmd->root_lock); + list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) { + if (td->open_count) + open_devices++; + else { + list_del(&td->list); + kfree(td); + } + } + up_read(&pmd->root_lock); + + if (open_devices) { + DMERR("attempt to close pmd when %u device(s) are still open", + open_devices); + return -EBUSY; + } + + if (pmd->sblock) { + down_write(&pmd->root_lock); + r = __commit_metadata(pmd); + if (r) + DMWARN("%s: dm_pool_commit_metadata() failed, error = %d", + __func__, r); + up_write(&pmd->root_lock); + } + + dm_tm_destroy(pmd->tm); + dm_tm_destroy(pmd->nb_tm); + dm_block_manager_destroy(pmd->bm); + dm_sm_destroy(pmd->metadata_sm); + dm_sm_destroy(pmd->data_sm); + kfree(pmd); + + return 0; +} + int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result) { int r;