From 4de6f58085c533c79ce2e0db6cdeb6ed06fe05f8 Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Sun, 27 Sep 2020 01:11:47 +0200 Subject: [PATCH] thin: use lv_status_thin and lv_status_thin_pool Introduce structures lv_status_thin_pool and lv_status_thin (pair to lv_status_cache, lv_status_vdo) Convert lv_thin_percent() -> lv_thin_status() and lv_thin_pool_percent() + lv_thin_pool_transaction_id() -> lv_thin_pool_status(). This way a function user can see not only percentages, but also other important status info about thin-pool. TODO: This patch tries to not change too many other things, but pool_below_threshold() now uses new thin-pool info to return failure if thin-pool cannot be actually modified. This should be handle separately in a better way. --- lib/activate/activate.c | 83 ++++++---------------- lib/activate/activate.h | 10 ++- lib/activate/dev_manager.c | 116 ++++++++++++++++++++----------- lib/activate/dev_manager.h | 16 ++--- lib/display/display.c | 22 +++--- lib/metadata/lv_manip.c | 26 ++++--- lib/metadata/metadata-exported.h | 14 ++++ lib/metadata/thin_manip.c | 73 ++++++++++++++----- lib/report/properties.c | 60 ++++++++++------ 9 files changed, 246 insertions(+), 174 deletions(-) diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 2e8f0e467..27f44e820 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -284,18 +284,13 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg) { return 0; } -int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, - dm_percent_t *percent) +int lv_thin_pool_status(const struct logical_volume *lv, int flush, + struct lv_status_thin_pool **thin_pool_status) { return 0; } -int lv_thin_percent(const struct logical_volume *lv, int mapped, - dm_percent_t *percent) -{ - return 0; -} -int lv_thin_pool_transaction_id(const struct logical_volume *lv, - uint64_t *transaction_id) +int lv_thin_status(const struct logical_volume *lv, int flush, + struct lv_status_thin **thin_status) { return 0; } @@ -1248,86 +1243,52 @@ int lv_cache_status(const struct logical_volume *cache_lv, return 1; } -/* - * Returns data or metadata percent usage, depends on metadata 0/1. - * Returns 1 if percent set, else 0 on failure. - */ -int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, - dm_percent_t *percent) +int lv_thin_pool_status(const struct logical_volume *lv, int flush, + struct lv_status_thin_pool **thin_pool_status) { - int r; struct dev_manager *dm; if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) return 0; - log_debug_activation("Checking thin %sdata percent for LV %s.", - (metadata) ? "meta" : "", display_lvname(lv)); + log_debug_activation("Checking thin pool status for LV %s.", + display_lvname(lv)); if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) return_0; - if (!(r = dev_manager_thin_pool_percent(dm, lv, metadata, percent))) - stack; + if (!dev_manager_thin_pool_status(dm, lv, flush, thin_pool_status)) { + dev_manager_destroy(dm); + return_0; + } - dev_manager_destroy(dm); + /* User has to call dm_pool_destroy(thin_pool_status->mem)! */ - return r; + return 1; } -/* - * Returns 1 if percent set, else 0 on failure. - */ -int lv_thin_percent(const struct logical_volume *lv, - int mapped, dm_percent_t *percent) +int lv_thin_status(const struct logical_volume *lv, int flush, + struct lv_status_thin **thin_status) { - int r; struct dev_manager *dm; if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0)) return 0; - log_debug_activation("Checking thin percent for LV %s.", + log_debug_activation("Checking thin status for LV %s.", display_lvname(lv)); if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) return_0; - if (!(r = dev_manager_thin_percent(dm, lv, mapped, percent))) - stack; - - dev_manager_destroy(dm); - - return r; -} - -/* - * Returns 1 if transaction_id set, else 0 on failure. - */ -int lv_thin_pool_transaction_id(const struct logical_volume *lv, - uint64_t *transaction_id) -{ - int r; - struct dev_manager *dm; - struct dm_status_thin_pool *status; - - if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) - return 0; - - log_debug_activation("Checking thin-pool transaction id for LV %s.", - display_lvname(lv)); - - if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1))) + if (!dev_manager_thin_status(dm, lv, flush, thin_status)) { + dev_manager_destroy(dm); return_0; + } - if (!(r = dev_manager_thin_pool_status(dm, lv, &status, 0))) - stack; - else - *transaction_id = status->transaction_id; + /* User has to call dm_pool_destroy(thin_status->mem)! */ - dev_manager_destroy(dm); - - return r; + return 1; } int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id) diff --git a/lib/activate/activate.h b/lib/activate/activate.h index e3c1bb35e..3f4d128be 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -191,13 +191,11 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg); int lv_writecache_message(const struct logical_volume *lv, const char *msg); int lv_cache_status(const struct logical_volume *cache_lv, struct lv_status_cache **status); -int lv_thin_pool_percent(const struct logical_volume *lv, int metadata, - dm_percent_t *percent); -int lv_thin_percent(const struct logical_volume *lv, int mapped, - dm_percent_t *percent); -int lv_thin_pool_transaction_id(const struct logical_volume *lv, - uint64_t *transaction_id); int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id); +int lv_thin_status(const struct logical_volume *lv, int flush, + struct lv_status_thin **status); +int lv_thin_pool_status(const struct logical_volume *lv, int flush, + struct lv_status_thin_pool **status); int lv_vdo_pool_status(const struct logical_volume *lv, int flush, struct lv_status_vdo **status); int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent); diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index a626b000a..85cfda246 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -1564,9 +1564,6 @@ int dev_manager_cache_status(struct dev_manager *dm, if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv)))) return_0; - if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache)))) - return_0; - if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0))) return_0; @@ -1589,8 +1586,11 @@ int dev_manager_cache_status(struct dev_manager *dm, if (!dm_get_status_cache(dm->mem, params, &c)) goto_out; - (*status)->cache = c; + if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache)))) + goto_out; + (*status)->mem = dm->mem; /* User has to destroy this mem pool later */ + (*status)->cache = c; if (c->fail || c->error) { (*status)->data_usage = (*status)->metadata_usage = @@ -1612,10 +1612,10 @@ out: } int dev_manager_thin_pool_status(struct dev_manager *dm, - const struct logical_volume *lv, - struct dm_status_thin_pool **status, - int flush) + const struct logical_volume *lv, int flush, + struct lv_status_thin_pool **status) { + struct dm_status_thin_pool *dm_status; const char *dlid; struct dm_task *dmt; struct dm_info info; @@ -1636,11 +1636,31 @@ int dev_manager_thin_pool_status(struct dev_manager *dm, dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms); - /* FIXME Check for thin and check there's exactly one target */ + if (!type || strcmp(type, TARGET_NAME_THIN_POOL)) { + log_error("Expected %s segment type but got %s instead.", + TARGET_NAME_THIN_POOL, type ? type : "NULL"); + goto out; + } - if (!dm_get_status_thin_pool(dm->mem, params, status)) + if (!dm_get_status_thin_pool(dm->mem, params, &dm_status)) goto_out; + if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin_pool)))) + goto_out; + + (*status)->mem = dm->mem; + (*status)->thin_pool = dm_status; + + if (dm_status->fail || dm_status->error) { + (*status)->data_usage = + (*status)->metadata_usage = DM_PERCENT_INVALID; + } else { + (*status)->data_usage = dm_make_percent(dm_status->used_data_blocks, + dm_status->total_data_blocks); + (*status)->metadata_usage = dm_make_percent(dm_status->used_metadata_blocks, + dm_status->total_metadata_blocks); + } + r = 1; out: dm_task_destroy(dmt); @@ -1648,52 +1668,68 @@ out: return r; } -int dev_manager_thin_pool_percent(struct dev_manager *dm, - const struct logical_volume *lv, - int metadata, dm_percent_t *percent) +int dev_manager_thin_status(struct dev_manager *dm, + const struct logical_volume *lv, int flush, + struct lv_status_thin **status) { - char *name; + struct dm_status_thin *dm_status; const char *dlid; - const char *layer = lv_layer(lv); + struct dm_task *dmt; + struct dm_info info; + uint64_t start, length; + char *type = NULL; + char *params = NULL; + uint64_t csize; + int r = 0; - /* Build a name for the top layer */ - if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv)))) return_0; - if (!(dlid = build_dm_uuid(dm->mem, lv, layer))) + if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0))) return_0; - log_debug_activation("Getting device status percentage for %s.", name); + if (!info.exists) + goto_out; - if (!(_percent(dm, name, dlid, TARGET_NAME_THIN_POOL, 0, - (metadata) ? lv : NULL, percent, NULL, 1))) - return_0; + dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms); - return 1; -} + if (!type || strcmp(type, TARGET_NAME_THIN)) { + log_error("Expected %s segment type but got %s instead.", + TARGET_NAME_THIN, type ? type : "NULL"); + goto out; + } -int dev_manager_thin_percent(struct dev_manager *dm, - const struct logical_volume *lv, - int mapped, dm_percent_t *percent) -{ - char *name; - const char *dlid; - const char *layer = lv_layer(lv); + if (!dm_get_status_thin(dm->mem, params, &dm_status)) + goto_out; - /* Build a name for the top layer */ - if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) - return_0; + if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin)))) + goto_out; - if (!(dlid = build_dm_uuid(dm->mem, lv, layer))) - return_0; + (*status)->mem = dm->mem; + (*status)->thin = dm_status; - log_debug_activation("Getting device status percentage for %s", name); + if (dm_status->fail) + (*status)->usage = DM_PERCENT_INVALID; + else { + /* Pool allocates whole chunk so round-up to nearest one */ + csize = first_seg(first_seg(lv)->pool_lv)->chunk_size; + csize = ((lv->size + csize - 1) / csize) * csize; + if (dm_status->mapped_sectors > csize) { + log_warn("WARNING: LV %s maps %s while the size is only %s.", + display_lvname(lv), + display_size(dm->cmd, dm_status->mapped_sectors), + display_size(dm->cmd, csize)); + /* Don't show nonsense numbers like i.e. 1000% full */ + dm_status->mapped_sectors = csize; + } + (*status)->usage = dm_make_percent(dm_status->mapped_sectors, csize); + } - if (!(_percent(dm, name, dlid, TARGET_NAME_THIN, 0, - (mapped) ? NULL : lv, percent, NULL, 1))) - return_0; + r = 1; +out: + dm_task_destroy(dmt); - return 1; + return r; } /* diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h index 5bff47799..557418201 100644 --- a/lib/activate/dev_manager.h +++ b/lib/activate/dev_manager.h @@ -69,19 +69,15 @@ int dev_manager_writecache_message(struct dev_manager *dm, int dev_manager_cache_status(struct dev_manager *dm, const struct logical_volume *lv, struct lv_status_cache **status); -int dev_manager_thin_pool_status(struct dev_manager *dm, - const struct logical_volume *lv, - struct dm_status_thin_pool **status, - int flush); -int dev_manager_thin_pool_percent(struct dev_manager *dm, - const struct logical_volume *lv, - int metadata, dm_percent_t *percent); -int dev_manager_thin_percent(struct dev_manager *dm, - const struct logical_volume *lv, - int mapped, dm_percent_t *percent); +int dev_manager_thin_status(struct dev_manager *dm, + const struct logical_volume *lv, int flush, + struct lv_status_thin **status); int dev_manager_thin_device_id(struct dev_manager *dm, const struct logical_volume *lv, uint32_t *device_id); +int dev_manager_thin_pool_status(struct dev_manager *dm, + const struct logical_volume *lv, int flush, + struct lv_status_thin_pool **status); int dev_manager_vdo_pool_status(struct dev_manager *dm, const struct logical_volume *lv, struct lv_status_vdo **vdo_status, diff --git a/lib/display/display.c b/lib/display/display.c index 36c9879b3..6ef46f1e8 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -406,10 +406,12 @@ int lvdisplay_full(struct cmd_context *cmd, struct lv_segment *seg = NULL; int lvm1compat; dm_percent_t snap_percent; - int thin_data_active = 0, thin_metadata_active = 0; + int thin_pool_active = 0; dm_percent_t thin_data_percent, thin_metadata_percent; int thin_active = 0; dm_percent_t thin_percent; + struct lv_status_thin *thin_status = NULL; + struct lv_status_thin_pool *thin_pool_status = NULL; struct lv_status_cache *cache_status = NULL; struct lv_status_vdo *vdo_status = NULL; @@ -503,15 +505,18 @@ int lvdisplay_full(struct cmd_context *cmd, if (seg->merge_lv) log_print("LV merging to %s", seg->merge_lv->name); - if (inkernel) - thin_active = lv_thin_percent(lv, 0, &thin_percent); + if (inkernel && (thin_active = lv_thin_status(lv, 0, &thin_status))) { + thin_percent = thin_status->usage; + dm_pool_destroy(thin_status->mem); + } if (lv_is_merging_origin(lv)) log_print("LV merged with %s", find_snapshot(lv)->lv->name); } else if (lv_is_thin_pool(lv)) { - if (lv_info(cmd, lv, 1, &info, 1, 1) && info.exists) { - thin_data_active = lv_thin_pool_percent(lv, 0, &thin_data_percent); - thin_metadata_active = lv_thin_pool_percent(lv, 1, &thin_metadata_percent); + if ((thin_pool_active = lv_thin_pool_status(lv, 0, &thin_pool_status))) { + thin_data_percent = thin_pool_status->data_usage; + thin_metadata_percent = thin_pool_status->metadata_usage; + dm_pool_destroy(thin_pool_status->mem); } /* FIXME: display thin_pool targets transid for activated LV as well */ seg = first_seg(lv); @@ -591,13 +596,12 @@ int lvdisplay_full(struct cmd_context *cmd, dm_pool_destroy(cache_status->mem); } - if (thin_data_active) + if (thin_pool_active) { log_print("Allocated pool data %s%%", display_percent(cmd, thin_data_percent)); - - if (thin_metadata_active) log_print("Allocated metadata %s%%", display_percent(cmd, thin_metadata_percent)); + } if (thin_active) log_print("Mapped size %s%%", diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 6a89f1ec0..d913607fa 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -4960,6 +4960,7 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv, dm_percent_t percent; dm_percent_t min_threshold; int policy_threshold, policy_amount; + struct lv_status_thin_pool *thin_pool_status; *amount = *meta_amount = 0; @@ -5009,18 +5010,19 @@ static int _lvresize_adjust_policy(const struct logical_volume *lv, } if (lv_is_thin_pool(lv)) { - if (!lv_thin_pool_percent(lv, 1, &percent)) + if (!lv_thin_pool_status(lv, 0, &thin_pool_status)) goto_bad; /* Resize below the minimal usable value */ min_threshold = pool_metadata_min_threshold(first_seg(lv)) / DM_PERCENT_1; - *meta_amount = _adjust_amount(percent, (min_threshold < policy_threshold) ? + *meta_amount = _adjust_amount(thin_pool_status->metadata_usage, + (min_threshold < policy_threshold) ? min_threshold : policy_threshold, policy_amount); if (*meta_amount) /* Compensate possible extra space consumption by kernel on resize */ (*meta_amount)++; - if (!lv_thin_pool_percent(lv, 0, &percent)) - goto_bad; + percent = thin_pool_status->data_usage; + dm_pool_destroy(thin_pool_status->mem); } else if (lv_is_vdo_pool(lv)) { if (!lv_vdo_pool_percent(lv, &percent)) goto_bad; @@ -8464,17 +8466,21 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, * and needs to be restored to the state from this canceled segment. * TODO: there is low chance actual suspend has failed */ - if (!lv_thin_pool_transaction_id(pool_lv, &transaction_id)) { + struct lv_status_thin_pool *tpstatus; + if (!lv_thin_pool_status(pool_lv, 1, &tpstatus)) log_error("Aborting. Failed to read transaction_id from thin pool %s.", display_lvname(pool_lv)); /* Can't even get thin pool transaction id ??? */ - } else if (transaction_id != first_seg(pool_lv)->transaction_id) { - if (transaction_id == seg->transaction_id) - log_debug_metadata("Reverting back transaction_id " FMTu64 " for thin pool %s.", - seg->transaction_id, display_lvname(pool_lv)); - else + else { + transaction_id = tpstatus->thin_pool->transaction_id; + dm_pool_destroy(tpstatus->mem); + + if ((transaction_id != first_seg(pool_lv)->transaction_id) && + (transaction_id != seg->transaction_id)) log_warn("WARNING: Metadata for thin pool %s have transaction_id " FMTu64 ", but active pool has " FMTu64 ".", display_lvname(pool_lv), seg->transaction_id, transaction_id); + log_debug_metadata("Restoring previous transaction_id " FMTu64 " for thin pool %s.", + seg->transaction_id, display_lvname(pool_lv)); first_seg(pool_lv)->transaction_id = seg->transaction_id; first_seg(lv)->device_id = 0; /* no delete of never existing thin device */ } diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index b109d5b6d..c4d51998b 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -887,6 +887,20 @@ int update_thin_pool_params(struct cmd_context *cmd, uint32_t *pool_metadata_extents, int *chunk_size_calc_method, uint32_t *chunk_size, thin_discards_t *discards, thin_zero_t *zero_new_blocks); + +struct lv_status_thin_pool { + struct dm_pool *mem; + struct dm_status_thin_pool *thin_pool; + dm_percent_t data_usage; + dm_percent_t metadata_usage; +}; + +struct lv_status_thin { + struct dm_pool *mem; + struct dm_status_thin *thin; + dm_percent_t usage; +}; + const char *get_pool_discards_name(thin_discards_t discards); int set_pool_discards(thin_discards_t *discards, const char *str); struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv, diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c index e3364ddc8..91d2317e3 100644 --- a/lib/metadata/thin_manip.c +++ b/lib/metadata/thin_manip.c @@ -243,49 +243,86 @@ int pool_metadata_min_threshold(const struct lv_segment *pool_seg) int pool_below_threshold(const struct lv_segment *pool_seg) { struct cmd_context *cmd = pool_seg->lv->vg->cmd; - dm_percent_t percent; + struct lv_status_thin_pool *thin_pool_status = NULL; dm_percent_t min_threshold = pool_metadata_min_threshold(pool_seg); dm_percent_t threshold = DM_PERCENT_1 * find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG, lv_config_profile(pool_seg->lv)); + int ret = 1; - /* Data */ - if (!lv_thin_pool_percent(pool_seg->lv, 0, &percent)) + if (threshold > DM_PERCENT_100) + threshold = DM_PERCENT_100; + + /* FIXME: currently with FLUSH - this may block pool while holding VG lock + * maybe try 2-phase version - 1st. check without commit + * 2nd. quickly following with commit */ + if (!lv_thin_pool_status(pool_seg->lv, 1, &thin_pool_status)) return_0; - if (percent > threshold || percent >= DM_PERCENT_100) { + if (thin_pool_status->thin_pool->fail | + thin_pool_status->thin_pool->out_of_data_space | + thin_pool_status->thin_pool->needs_check | + thin_pool_status->thin_pool->error | + thin_pool_status->thin_pool->read_only) { + log_warn("WARNING: Thin pool %s%s%s%s%s%s.", + display_lvname(pool_seg->lv), + thin_pool_status->thin_pool->fail ? " is failed" : "", + thin_pool_status->thin_pool->out_of_data_space ? " is out of data space" : "", + thin_pool_status->thin_pool->needs_check ? " needs check" : "", + thin_pool_status->thin_pool->error ? " is erroring" : "", + thin_pool_status->thin_pool->read_only ? " has read-only metadata" : ""); + ret = 0; + if (thin_pool_status->thin_pool->fail) + goto out; + } + + /* Data */ + + if (thin_pool_status->data_usage > threshold) { log_debug("Threshold configured for free data space in " "thin pool %s has been reached (%s%% >= %s%%).", display_lvname(pool_seg->lv), - display_percent(cmd, percent), + display_percent(cmd, thin_pool_status->data_usage), display_percent(cmd, threshold)); - return 0; + ret = 0; } /* Metadata */ - if (!lv_thin_pool_percent(pool_seg->lv, 1, &percent)) - return_0; - if (percent >= min_threshold) { + if (thin_pool_status->metadata_usage >= min_threshold) { log_warn("WARNING: Remaining free space in metadata of thin pool %s " "is too low (%s%% >= %s%%). " "Resize is recommended.", display_lvname(pool_seg->lv), - display_percent(cmd, percent), + display_percent(cmd, thin_pool_status->metadata_usage), display_percent(cmd, min_threshold)); - return 0; + ret = 0; } - if (percent > threshold) { + if (thin_pool_status->metadata_usage > threshold) { log_debug("Threshold configured for free metadata space in " "thin pool %s has been reached (%s%% > %s%%).", display_lvname(pool_seg->lv), - display_percent(cmd, percent), + display_percent(cmd, thin_pool_status->metadata_usage), display_percent(cmd, threshold)); - return 0; + ret = 0; } - return 1; + if ((thin_pool_status->thin_pool->transaction_id != pool_seg->transaction_id) && + (dm_list_empty(&pool_seg->thin_messages) || + ((thin_pool_status->thin_pool->transaction_id + 1) != pool_seg->transaction_id))) { + log_warn("WARNING: Thin pool %s has unexpected transaction id " FMTu64 + ", expecting " FMTu64 "%s.", + display_lvname(pool_seg->lv), + thin_pool_status->thin_pool->transaction_id, + pool_seg->transaction_id, + dm_list_empty(&pool_seg->thin_messages) ? "" : " or lower by 1"); + ret = 0; + } +out: + dm_pool_destroy(thin_pool_status->mem); + + return ret; } /* @@ -853,6 +890,7 @@ int check_new_thin_pool(const struct logical_volume *pool_lv) { struct cmd_context *cmd = pool_lv->vg->cmd; uint64_t transaction_id; + struct lv_status_thin_pool *status = NULL; /* For transaction_id check LOCAL activation is required */ if (!activate_lv(cmd, pool_lv)) { @@ -862,12 +900,15 @@ int check_new_thin_pool(const struct logical_volume *pool_lv) } /* With volume lists, check pool really is locally active */ - if (!lv_thin_pool_transaction_id(pool_lv, &transaction_id)) { + if (!lv_thin_pool_status(pool_lv, 1, &status)) { log_error("Cannot read thin pool %s transaction id locally, perhaps skipped in lvm.conf volume_list?", display_lvname(pool_lv)); return 0; } + transaction_id = status->thin_pool->transaction_id; + dm_pool_destroy(status->mem); + /* 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 " diff --git a/lib/report/properties.c b/lib/report/properties.c index d4ac8c47e..ef2888f50 100644 --- a/lib/report/properties.c +++ b/lib/report/properties.c @@ -142,47 +142,63 @@ static dm_percent_t _snap_percent(const struct logical_volume *lv) static dm_percent_t _data_percent(const struct logical_volume *lv) { - dm_percent_t percent; - struct lv_status_cache *status; + dm_percent_t percent = DM_PERCENT_INVALID; + struct lv_status_cache *cache_status; + struct lv_status_thin *thin_status; + struct lv_status_thin_pool *thin_pool_status; if (lv_is_cow(lv)) return _snap_percent(lv); if (lv_is_cache(lv) || lv_is_used_cache_pool(lv)) { - if (!lv_cache_status(lv, &status)) { + if (!lv_cache_status(lv, &cache_status)) stack; - return DM_PERCENT_INVALID; + else { + percent = cache_status->data_usage; + dm_pool_destroy(cache_status->mem); + } + } else if (lv_is_thin_volume(lv)) { + if (!lv_thin_status(lv, 0, &thin_status)) + stack; + else { + percent = thin_status->usage; + dm_pool_destroy(thin_status->mem); + } + } else if (lv_is_thin_pool(lv)) { + if (!lv_thin_pool_status(lv, 0, &thin_pool_status)) + stack; + else { + percent = thin_pool_status->metadata_usage; + dm_pool_destroy(thin_pool_status->mem); } - percent = status->data_usage; - dm_pool_destroy(status->mem); - return percent; } - if (lv_is_thin_volume(lv)) - return lv_thin_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; - - return lv_thin_pool_percent(lv, 0, &percent) ? percent : DM_PERCENT_INVALID; + return percent; } static dm_percent_t _metadata_percent(const struct logical_volume *lv) { - dm_percent_t percent; - struct lv_status_cache *status; + dm_percent_t percent = DM_PERCENT_INVALID; + struct lv_status_cache *cache_status; + struct lv_status_thin_pool *thin_pool_status; if (lv_is_cache(lv) || lv_is_used_cache_pool(lv)) { - if (!lv_cache_status(lv, &status)) { + if (!lv_cache_status(lv, &cache_status)) stack; - return DM_PERCENT_INVALID; + else { + percent = cache_status->metadata_usage; + dm_pool_destroy(cache_status->mem); + } + } else if (lv_is_thin_pool(lv)) { + if (!lv_thin_pool_status(lv, 0, &thin_pool_status)) + stack; + else { + percent = thin_pool_status->metadata_usage; + dm_pool_destroy(thin_pool_status->mem); } - percent = status->metadata_usage; - dm_pool_destroy(status->mem); - return percent; } - if (lv_is_thin_pool(lv)) - return lv_thin_pool_percent(lv, 1, &percent) ? percent : DM_PERCENT_INVALID; - - return DM_PERCENT_INVALID; + return percent; } /* PV */