mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-03 09:04:21 +08:00
dm thin: allow pool in read-only mode to transition to read-write mode
A thin-pool may be in read-only mode because the pool's data or metadata space was exhausted. To allow for recovery, by adding more space to the pool, we must allow a pool to transition from PM_READ_ONLY to PM_WRITE mode. Otherwise, running out of space will render the pool permanently read-only. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
5383ef3a92
commit
9b7aaa64f9
@ -1697,6 +1697,14 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
|
||||
up_write(&pmd->root_lock);
|
||||
}
|
||||
|
||||
void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd)
|
||||
{
|
||||
down_write(&pmd->root_lock);
|
||||
pmd->read_only = false;
|
||||
dm_bm_set_read_write(pmd->bm);
|
||||
up_write(&pmd->root_lock);
|
||||
}
|
||||
|
||||
int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
|
||||
dm_block_t threshold,
|
||||
dm_sm_threshold_fn fn,
|
||||
|
@ -193,6 +193,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
|
||||
* that nothing is changing.
|
||||
*/
|
||||
void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
|
||||
void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd);
|
||||
|
||||
int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
|
||||
dm_block_t threshold,
|
||||
|
@ -1425,6 +1425,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
|
||||
break;
|
||||
|
||||
case PM_WRITE:
|
||||
dm_pool_metadata_read_write(pool->pmd);
|
||||
pool->process_bio = process_bio;
|
||||
pool->process_discard = process_discard;
|
||||
pool->process_prepared_mapping = process_prepared_mapping;
|
||||
@ -1641,12 +1642,19 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
|
||||
struct pool_c *pt = ti->private;
|
||||
|
||||
/*
|
||||
* We want to make sure that degraded pools are never upgraded.
|
||||
* We want to make sure that a pool in PM_FAIL mode is never upgraded.
|
||||
*/
|
||||
enum pool_mode old_mode = pool->pf.mode;
|
||||
enum pool_mode new_mode = pt->adjusted_pf.mode;
|
||||
|
||||
if (old_mode > new_mode)
|
||||
/*
|
||||
* If we were in PM_FAIL mode, rollback of metadata failed. We're
|
||||
* not going to recover without a thin_repair. So we never let the
|
||||
* pool move out of the old mode. On the other hand a PM_READ_ONLY
|
||||
* may have been due to a lack of metadata or data space, and may
|
||||
* now work (ie. if the underlying devices have been resized).
|
||||
*/
|
||||
if (old_mode == PM_FAIL)
|
||||
new_mode = old_mode;
|
||||
|
||||
pool->ti = ti;
|
||||
|
@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
|
||||
|
||||
void dm_bm_set_read_write(struct dm_block_manager *bm)
|
||||
{
|
||||
bm->read_only = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
|
||||
|
||||
u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
|
||||
{
|
||||
return crc32c(~(u32) 0, data, len) ^ init_xor;
|
||||
|
@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b);
|
||||
int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
|
||||
struct dm_block *superblock);
|
||||
|
||||
/*
|
||||
* Request data be prefetched into the cache.
|
||||
*/
|
||||
/*
|
||||
* Request data is prefetched into the cache.
|
||||
*/
|
||||
void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
|
||||
|
||||
/*
|
||||
@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
|
||||
* be returned if you do.
|
||||
*/
|
||||
void dm_bm_set_read_only(struct dm_block_manager *bm);
|
||||
void dm_bm_set_read_write(struct dm_block_manager *bm);
|
||||
|
||||
u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user