[dm-devel] [PATCH 09/13] dm thin: held root support
Mike Snitzer
snitzer at redhat.com
Wed Feb 29 14:50:13 UTC 2012
From: Joe Thornber <ejt at redhat.com>
This allows userland access to the thinp data mappings.
Signed-off-by: Joe Thornber <ejt at redhat.com>
---
Documentation/device-mapper/thin-provisioning.txt | 11 +++
drivers/md/dm-thin-metadata.c | 78 ++++++++++++++++++++-
drivers/md/dm-thin-metadata.h | 1 +
drivers/md/dm-thin.c | 38 ++++++++++
4 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt
index 60fc5cf..13e42fb 100644
--- a/Documentation/device-mapper/thin-provisioning.txt
+++ b/Documentation/device-mapper/thin-provisioning.txt
@@ -289,6 +289,17 @@ iii) Messages
the current transaction id is when you change it with this
compare-and-swap message.
+ hold_root
+
+ Reserve a copy of the data mapping btree for use by userland.
+ This allows userland to inspect the mappings as they were when
+ this message was executed. Use the pool's status command to
+ get the root block.
+
+ release_root
+
+ Release a previously reserved copy of the data mapping btree.
+
'thin' target
-------------
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 0bc3033..f3ba61d 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1081,10 +1081,46 @@ int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
return 0;
}
-static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
- dm_block_t *result)
+static int __hold_metadata_root(struct dm_pool_metadata *pmd)
+{
+ int r, r2;
+ struct thin_disk_superblock *disk_super;
+ struct dm_block *sblock;
+
+ r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ return r;
+
+ disk_super = dm_block_data(sblock);
+ if (le64_to_cpu(disk_super->held_root)) {
+ DMWARN("pool already has a held root");
+ r = -EBUSY;
+ } else {
+ __le64 root = disk_super->data_mapping_root;
+ dm_sm_inc_block(pmd->metadata_sm, le64_to_cpu(root));
+ disk_super->held_root = root;
+ pmd->need_commit = 1;
+ }
+
+ r2 = dm_bm_unlock(sblock);
+ return r ? r : r2;
+}
+
+int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd)
{
int r;
+
+ down_write(&pmd->root_lock);
+ r = __hold_metadata_root(pmd);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+static int __release_metadata_root(struct dm_pool_metadata *pmd)
+{
+ int r, r2;
struct thin_disk_superblock *disk_super;
struct dm_block *sblock;
@@ -1094,6 +1130,44 @@ static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
return r;
disk_super = dm_block_data(sblock);
+ if (!le64_to_cpu(disk_super->held_root)) {
+ DMWARN("pool has no held root");
+ r = -EINVAL;
+ } else {
+ __le64 root = disk_super->held_root;
+ dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(root));
+ disk_super->held_root = cpu_to_le64(0ULL);
+ pmd->need_commit = 1;
+ }
+
+ r2 = dm_bm_unlock(sblock);
+ return r ? r : r2;
+}
+
+int dm_pool_release_metadata_root(struct dm_pool_metadata *pmd)
+{
+ int r;
+
+ down_write(&pmd->root_lock);
+ r = __release_metadata_root(pmd);
+ up_write(&pmd->root_lock);
+
+ return r;
+}
+
+static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
+ dm_block_t *result)
+{
+ int r;
+ struct thin_disk_superblock *disk_super;
+ struct dm_block *sblock;
+
+ r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+ &sb_validator, &sblock);
+ if (r)
+ return r;
+
+ disk_super = dm_block_data(sblock);
*result = le64_to_cpu(disk_super->held_root);
return dm_bm_unlock(sblock);
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 859c168..cfc7d0b 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -79,6 +79,7 @@ int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
* Hold/get root for userspace transaction.
*/
int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd);
+int dm_pool_release_metadata_root(struct dm_pool_metadata *pmd);
int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
dm_block_t *result);
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index c143cf1..2e7c1bc 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2107,6 +2107,36 @@ static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct po
return 0;
}
+static int process_hold_root_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ int r;
+
+ r = check_arg_count(argc, 1);
+ if (r)
+ return r;
+
+ r = dm_pool_hold_metadata_root(pool->pmd);
+ if (r)
+ DMWARN("hold root request failed");
+
+ return r;
+}
+
+static int process_release_root_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+ int r;
+
+ r = check_arg_count(argc, 1);
+ if (r)
+ return r;
+
+ r = dm_pool_release_metadata_root(pool->pmd);
+ if (r)
+ DMWARN("release root request failed");
+
+ return r;
+}
+
/*
* Messages supported:
* create_thin <dev_id>
@@ -2114,6 +2144,8 @@ static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct po
* delete <dev_id>
* trim <dev_id> <new_size_in_sectors>
* set_transaction_id <current_trans_id> <new_trans_id>
+ * hold_root
+ * release_root
*/
static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
{
@@ -2133,6 +2165,12 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
else if (!strcasecmp(argv[0], "set_transaction_id"))
r = process_set_transaction_id_mesg(argc, argv, pool);
+ else if (!strcasecmp(argv[0], "hold_root"))
+ r = process_hold_root_mesg(argc, argv, pool);
+
+ else if (!strcasecmp(argv[0], "release_root"))
+ r = process_release_root_mesg(argc, argv, pool);
+
else
DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
--
1.7.1
More information about the dm-devel
mailing list