[dm-devel] [PATCH for-dm-3.14-fixes 3/8] dm thin: set flag if metadata is out of space
Mike Snitzer
snitzer at redhat.com
Fri Feb 21 02:56:00 UTC 2014
It is difficult for the metadata space map to accurately account for its
free space. Manually establish a flag that reflects this out of space
condition -- until/unless dm_pool_get_free_metadata_block_count() can
return a known out of space value (either 0 or some fixed reserve
threshold we create).
Signed-off-by: Mike Snitzer <snitzer at redhat.com>
---
drivers/md/dm-thin-metadata.c | 33 ++++++++++++++++++++++++++++++++-
drivers/md/dm-thin-metadata.h | 7 +++++++
drivers/md/dm-thin.c | 8 +++-----
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 3bb4506..21f3998 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -192,6 +192,15 @@ struct dm_pool_metadata {
* operation possible in this state is the closing of the device.
*/
bool fail_io:1;
+
+ /*
+ * Set if metadata space has been exhausted. It is difficult for the
+ * metadata space map to accurately account for its free space. So
+ * until/unless dm_pool_get_free_metadata_block_count can return a known
+ * out of space value (either 0 or some fixed reserve threshold we create)
+ * manually establish a flag that reflects this out of space condition.
+ */
+ bool metadata_out_of_space:1;
};
struct dm_thin_device {
@@ -815,6 +824,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
INIT_LIST_HEAD(&pmd->thin_devices);
pmd->read_only = false;
pmd->fail_io = false;
+ pmd->metadata_out_of_space = false;
pmd->bdev = bdev;
pmd->data_block_size = data_block_size;
@@ -1603,6 +1613,24 @@ int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
return r;
}
+void dm_pool_set_metadata_out_of_space(struct dm_pool_metadata *pmd)
+{
+ down_write(&pmd->root_lock);
+ pmd->metadata_out_of_space = true;
+ up_write(&pmd->root_lock);
+}
+
+bool dm_pool_is_metadata_out_of_space(struct dm_pool_metadata *pmd)
+{
+ bool r;
+
+ down_read(&pmd->root_lock);
+ r = pmd->metadata_out_of_space;
+ up_read(&pmd->root_lock);
+
+ return r;
+}
+
int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
dm_block_t *result)
{
@@ -1719,8 +1747,11 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_cou
int r = -EINVAL;
down_write(&pmd->root_lock);
- if (!pmd->fail_io)
+ if (!pmd->fail_io) {
r = __resize_space_map(pmd->metadata_sm, new_count);
+ if (!r)
+ pmd->metadata_out_of_space = false;
+ }
up_write(&pmd->root_lock);
return r;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index dd6088a..cc78fbb 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -91,6 +91,11 @@ int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
int dm_pool_abort_metadata(struct dm_pool_metadata *pmd);
/*
+ * Set if metadata space has been exhausted.
+ */
+void dm_pool_set_metadata_out_of_space(struct dm_pool_metadata *pmd);
+
+/*
* Set/get userspace transaction id.
*/
int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
@@ -185,6 +190,8 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+bool dm_pool_is_metadata_out_of_space(struct dm_pool_metadata *pmd);
+
/*
* Returns -ENOSPC if the new size is too small and already allocated
* blocks would be lost.
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 42d08eb..8e68831 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1464,16 +1464,14 @@ static void out_of_data_space(struct pool *pool)
static void metadata_operation_failed(struct pool *pool, const char *op, int r)
{
- dm_block_t free_blocks;
-
DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
dm_device_name(pool->pool_md), op, r);
- if (r == -ENOSPC &&
- !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
- !free_blocks)
+ if (r == -ENOSPC) {
+ dm_pool_set_metadata_out_of_space(pool->pmd);
DMERR_LIMIT("%s: no free metadata space available.",
dm_device_name(pool->pool_md));
+ }
set_pool_mode(pool, PM_READ_ONLY);
}
--
1.8.3.1
More information about the dm-devel
mailing list