dm thin: handle metadata failures more consistently
Introduce metadata_operation_failed() wrappers, around set_pool_mode(), to assist with improving the consistency of how metadata failures are handled. Logging is improved and metadata operation failures trigger read-only mode immediately. Also, eliminate redundant set_pool_mode() calls in the two alloc_data_block() caller's error paths. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
88a6621bed
commit
b533065585
1 changed files with 27 additions and 21 deletions
|
@ -198,7 +198,7 @@ struct pool {
|
|||
};
|
||||
|
||||
static enum pool_mode get_pool_mode(struct pool *pool);
|
||||
static void set_pool_mode(struct pool *pool, enum pool_mode mode);
|
||||
static void metadata_operation_failed(struct pool *pool, const char *op, int r);
|
||||
|
||||
/*
|
||||
* Target context for a pool.
|
||||
|
@ -641,9 +641,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
|
|||
*/
|
||||
r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
|
||||
if (r) {
|
||||
DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
|
||||
dm_device_name(pool->pool_md), r);
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
metadata_operation_failed(pool, "dm_thin_insert_block", r);
|
||||
cell_error(pool, m->cell);
|
||||
goto out;
|
||||
}
|
||||
|
@ -900,11 +898,8 @@ static int commit(struct pool *pool)
|
|||
return -EINVAL;
|
||||
|
||||
r = dm_pool_commit_metadata(pool->pmd);
|
||||
if (r) {
|
||||
DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d",
|
||||
dm_device_name(pool->pool_md), r);
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
}
|
||||
if (r)
|
||||
metadata_operation_failed(pool, "dm_pool_commit_metadata", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -941,8 +936,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
|
|||
return -EINVAL;
|
||||
|
||||
r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
|
||||
if (r)
|
||||
if (r) {
|
||||
metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
check_low_water_mark(pool, free_blocks);
|
||||
|
||||
|
@ -956,8 +953,10 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
|
|||
return r;
|
||||
|
||||
r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
|
||||
if (r)
|
||||
if (r) {
|
||||
metadata_operation_failed(pool, "dm_pool_get_free_block_count", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still have no space we set a flag to avoid
|
||||
|
@ -980,11 +979,11 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
|
|||
if (r) {
|
||||
if (r == -ENOSPC &&
|
||||
!dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
|
||||
!free_blocks) {
|
||||
!free_blocks)
|
||||
DMWARN("%s: no free metadata space available.",
|
||||
dm_device_name(pool->pool_md));
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
}
|
||||
|
||||
metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1125,6 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
|
|||
default:
|
||||
DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
|
||||
__func__, r);
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
cell_error(pool, cell);
|
||||
break;
|
||||
}
|
||||
|
@ -1205,7 +1203,6 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
|
|||
default:
|
||||
DMERR_LIMIT("%s: alloc_data_block() failed: error = %d",
|
||||
__func__, r);
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
cell_error(pool, cell);
|
||||
break;
|
||||
}
|
||||
|
@ -1449,6 +1446,18 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rather than calling set_pool_mode directly, use these which describe the
|
||||
* reason for mode degradation.
|
||||
*/
|
||||
static void metadata_operation_failed(struct pool *pool, const char *op, int r)
|
||||
{
|
||||
DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
|
||||
dm_device_name(pool->pool_md), op, r);
|
||||
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -2209,9 +2218,7 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
|
|||
} else if (data_size > sb_data_size) {
|
||||
r = dm_pool_resize_data_dev(pool->pmd, data_size);
|
||||
if (r) {
|
||||
DMERR("%s: failed to resize data device",
|
||||
dm_device_name(pool->pool_md));
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
metadata_operation_failed(pool, "dm_pool_resize_data_dev", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2248,8 +2255,7 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
|
|||
} else if (metadata_dev_size > sb_metadata_dev_size) {
|
||||
r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
|
||||
if (r) {
|
||||
DMERR("%s: failed to resize metadata device",
|
||||
dm_device_name(pool->pool_md));
|
||||
metadata_operation_failed(pool, "dm_pool_resize_metadata_dev", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue