diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2014-11-04 15:06:55 +0100 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2014-11-04 15:28:00 +0100 |
commit | 6116b1d6e302097086c9dcd418e4404ddd337939 (patch) | |
tree | f4a256c29e2f382596bd520ec6ff7774a3ca9ec9 | |
parent | ee627884de95ae5a40f0fc2534dcd60e63e2a58d (diff) | |
download | lvm2-6116b1d6e302097086c9dcd418e4404ddd337939.tar.gz |
thin: validate unused thin pool
Function tests, that given new thin pool is still unused.
-rw-r--r-- | lib/metadata/metadata.h | 3 | ||||
-rw-r--r-- | lib/metadata/thin_manip.c | 52 |
2 files changed, 55 insertions, 0 deletions
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 1dd88674e..48c1b3c85 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -389,6 +389,9 @@ struct lv_segment *find_pool_seg(const struct lv_segment *seg); /* Find some unused device_id for thin pool LV segment. */ uint32_t get_free_pool_device_id(struct lv_segment *thin_pool_seg); +/* Check if the new thin-pool could be used for lvm2 thin volumes */ +int check_new_thin_pool(const struct logical_volume *pool_lv); + /* * Remove a dev_dir if present. */ diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c index 8569ac174..50354cc82 100644 --- a/lib/metadata/thin_manip.c +++ b/lib/metadata/thin_manip.c @@ -569,3 +569,55 @@ int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count) return r; } + +/* + * Explict check of new thin pool for usability + * + * Allow use of thin pools by external apps. When lvm2 metadata has + * transaction_id == 0 for a new thin pool, it will explicitely validate + * the pool is still unused. + * + * To prevent lvm2 to create thin volumes in externally used thin pools + * simply increment its transaction_id. + */ +int check_new_thin_pool(const struct logical_volume *pool_lv) +{ + struct cmd_context *cmd = pool_lv->vg->cmd; + uint64_t transaction_id; + + /* For transaction_id check LOCAL activation is required */ + if (!activate_lv_excl_local(cmd, pool_lv)) { + log_error("Aborting. Failed to locally activate thin pool %s.", + display_lvname(pool_lv)); + return 0; + } + + /* With volume lists, check pool really is locally active */ + if (!lv_thin_pool_transaction_id(pool_lv, &transaction_id)) { + log_error("Cannot read thin pool %s transaction id locally, perhaps skipped in lvm.conf volume_list?", + display_lvname(pool_lv)); + return 0; + } + + /* Require pool to have same transaction_id as new */ + if (first_seg(pool_lv)->transaction_id != transaction_id) { + log_error("Cannot use thin pool %s with transaction id " + "%" PRIu64 " for thin volumes. " + "Expected transaction id %" PRIu64 ".", + display_lvname(pool_lv), transaction_id, + first_seg(pool_lv)->transaction_id); + return 0; + } + + log_verbose("Deactivating public thin pool %s", + display_lvname(pool_lv)); + + /* Prevent any 'race' with in-use thin pool and always deactivate */ + if (!deactivate_lv(pool_lv->vg->cmd, pool_lv)) { + log_error("Aborting. Could not deactivate thin pool %s.", + display_lvname(pool_lv)); + return 0; + } + + return 1; +} |