未验证 提交 6d6a64d3 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!1014 [sync] PR-920: dm thin: Fix ABBA deadlock by resetting dm_bufio_client

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/920 
 
PR sync from:  Li Lingfeng <lilingfeng3@huawei.com>
 https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/thread/XNE65PIJUOQRSLID56LFRUSB3FNDYMGE/ 
 
 
Link:https://gitee.com/openeuler/kernel/pulls/1014 

Reviewed-by: zhangyi (F) <yi.zhang@huawei.com> 
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> 
......@@ -1883,6 +1883,13 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c)
}
EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
void dm_bufio_client_reset(struct dm_bufio_client *c)
{
drop_buffers(c);
flush_work(&c->shrink_work);
}
EXPORT_SYMBOL_GPL(dm_bufio_client_reset);
void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start)
{
c->start = start;
......
......@@ -574,6 +574,8 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
r = dm_tm_create_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION,
&pmd->tm, &pmd->metadata_sm);
if (r < 0) {
pmd->tm = NULL;
pmd->metadata_sm = NULL;
DMERR("tm_create_with_sm failed");
return r;
}
......@@ -582,6 +584,7 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
if (IS_ERR(pmd->data_sm)) {
DMERR("sm_disk_create failed");
r = PTR_ERR(pmd->data_sm);
pmd->data_sm = NULL;
goto bad_cleanup_tm;
}
......@@ -612,11 +615,15 @@ static int __format_metadata(struct dm_pool_metadata *pmd)
bad_cleanup_nb_tm:
dm_tm_destroy(pmd->nb_tm);
pmd->nb_tm = NULL;
bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm);
pmd->data_sm = NULL;
bad_cleanup_tm:
dm_tm_destroy(pmd->tm);
pmd->tm = NULL;
dm_sm_destroy(pmd->metadata_sm);
pmd->metadata_sm = NULL;
return r;
}
......@@ -682,6 +689,8 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
sizeof(disk_super->metadata_space_map_root),
&pmd->tm, &pmd->metadata_sm);
if (r < 0) {
pmd->tm = NULL;
pmd->metadata_sm = NULL;
DMERR("tm_open_with_sm failed");
goto bad_unlock_sblock;
}
......@@ -691,6 +700,7 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
if (IS_ERR(pmd->data_sm)) {
DMERR("sm_disk_open failed");
r = PTR_ERR(pmd->data_sm);
pmd->data_sm = NULL;
goto bad_cleanup_tm;
}
......@@ -717,9 +727,12 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm);
pmd->data_sm = NULL;
bad_cleanup_tm:
dm_tm_destroy(pmd->tm);
pmd->tm = NULL;
dm_sm_destroy(pmd->metadata_sm);
pmd->metadata_sm = NULL;
bad_unlock_sblock:
dm_bm_unlock(sblock);
......@@ -766,9 +779,13 @@ static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd,
bool destroy_bm)
{
dm_sm_destroy(pmd->data_sm);
pmd->data_sm = NULL;
dm_sm_destroy(pmd->metadata_sm);
pmd->metadata_sm = NULL;
dm_tm_destroy(pmd->nb_tm);
pmd->nb_tm = NULL;
dm_tm_destroy(pmd->tm);
pmd->tm = NULL;
if (destroy_bm)
dm_block_manager_destroy(pmd->bm);
}
......@@ -976,8 +993,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
__func__, r);
}
pmd_write_unlock(pmd);
if (!pmd->fail_io)
__destroy_persistent_data_objects(pmd, true);
__destroy_persistent_data_objects(pmd, true);
kfree(pmd);
return 0;
......@@ -1884,53 +1900,30 @@ static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd)
int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
{
int r = -EINVAL;
struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
/* fail_io is double-checked with pmd->root_lock held below */
if (unlikely(pmd->fail_io))
return r;
/*
* Replacement block manager (new_bm) is created and old_bm destroyed outside of
* pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
* shrinker associated with the block manager's bufio client vs pmd root_lock).
* - must take shrinker_rwsem without holding pmd->root_lock
*/
new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
THIN_MAX_CONCURRENT_LOCKS);
pmd_write_lock(pmd);
if (pmd->fail_io) {
pmd_write_unlock(pmd);
goto out;
return r;
}
__set_abort_with_changes_flags(pmd);
/* destroy data_sm/metadata_sm/nb_tm/tm */
__destroy_persistent_data_objects(pmd, false);
old_bm = pmd->bm;
if (IS_ERR(new_bm)) {
DMERR("could not create block manager during abort");
pmd->bm = NULL;
r = PTR_ERR(new_bm);
goto out_unlock;
}
pmd->bm = new_bm;
/* reset bm */
dm_block_manager_reset(pmd->bm);
/* rebuild data_sm/metadata_sm/nb_tm/tm */
r = __open_or_format_metadata(pmd, false);
if (r) {
pmd->bm = NULL;
goto out_unlock;
}
new_bm = NULL;
out_unlock:
if (r)
pmd->fail_io = true;
pmd_write_unlock(pmd);
dm_block_manager_destroy(old_bm);
out:
if (new_bm && !IS_ERR(new_bm))
dm_block_manager_destroy(new_bm);
pmd_write_unlock(pmd);
return r;
}
......
......@@ -414,6 +414,12 @@ void dm_block_manager_destroy(struct dm_block_manager *bm)
}
EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
void dm_block_manager_reset(struct dm_block_manager *bm)
{
dm_bufio_client_reset(bm->bufio);
}
EXPORT_SYMBOL_GPL(dm_block_manager_reset);
unsigned dm_bm_block_size(struct dm_block_manager *bm)
{
return dm_bufio_get_block_size(bm->bufio);
......
......@@ -35,6 +35,7 @@ struct dm_block_manager *dm_block_manager_create(
struct block_device *bdev, unsigned block_size,
unsigned max_held_per_thread);
void dm_block_manager_destroy(struct dm_block_manager *bm);
void dm_block_manager_reset(struct dm_block_manager *bm);
unsigned dm_bm_block_size(struct dm_block_manager *bm);
dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
......
......@@ -76,7 +76,8 @@ struct dm_space_map {
static inline void dm_sm_destroy(struct dm_space_map *sm)
{
sm->destroy(sm);
if (sm)
sm->destroy(sm);
}
static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
......
......@@ -197,6 +197,9 @@ EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
void dm_tm_destroy(struct dm_transaction_manager *tm)
{
if (!tm)
return;
if (!tm->is_clone)
wipe_shadow_table(tm);
......
......@@ -31,6 +31,8 @@ dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
*/
void dm_bufio_client_destroy(struct dm_bufio_client *c);
void dm_bufio_client_reset(struct dm_bufio_client *c);
/*
* Set the sector range.
* When this function is called, there must be no I/O in progress on the bufio
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册