]> sourceware.org Git - lvm2.git/commitdiff
thin: use lv_status_thin and lv_status_thin_pool
authorZdenek Kabelac <zkabelac@redhat.com>
Sat, 26 Sep 2020 23:11:47 +0000 (01:11 +0200)
committerZdenek Kabelac <zkabelac@redhat.com>
Tue, 29 Sep 2020 08:43:56 +0000 (10:43 +0200)
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
lib/activate/activate.h
lib/activate/dev_manager.c
lib/activate/dev_manager.h
lib/display/display.c
lib/metadata/lv_manip.c
lib/metadata/metadata-exported.h
lib/metadata/thin_manip.c
lib/report/properties.c

index 2e8f0e467cbadd010b8a5c957267ca4da0e0c6aa..27f44e8200b7027700e9743b18a14aa235e9d6f7 100644 (file)
@@ -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;
-
-       dev_manager_destroy(dm);
+       /* User has to call dm_pool_destroy(thin_status->mem)! */
 
-       return r;
+       return 1;
 }
 
 int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
index e3c1bb35ed7742383bf370f6efb22d1587254b2b..3f4d128be07a411d0c060c8254e9586fac967814 100644 (file)
@@ -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);
index a626b000ab87def4570bec720945eb5ff97d9390..85cfda246f424b5d40aa6253a8a20f5d11cefef2 100644 (file)
@@ -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, &params);
 
-       /* 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 (!(_percent(dm, name, dlid, TARGET_NAME_THIN_POOL, 0,
-                      (metadata) ? lv : NULL, percent, NULL, 1)))
-               return_0;
+       if (!info.exists)
+               goto_out;
 
-       return 1;
-}
+       dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
 
-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 (!type || strcmp(type, TARGET_NAME_THIN)) {
+               log_error("Expected %s segment type but got %s instead.",
+                         TARGET_NAME_THIN, type ? type : "NULL");
+               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 (!dm_get_status_thin(dm->mem, params, &dm_status))
+               goto_out;
 
-       if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
-               return_0;
+       if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin))))
+               goto_out;
 
-       log_debug_activation("Getting device status percentage for %s", name);
+       (*status)->mem = dm->mem;
+       (*status)->thin = dm_status;
+
+       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;
 }
 
 /*
index 5bff477995ef3cfc4b132f8da71a87345b6c63e2..55741820152e14457ae7b41eec784a96fd55ea4b 100644 (file)
@@ -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,
index 36c9879b3011d6ad2ca7987da50e1b66396c5157..6ef46f1e8f93d54b281eaf8d6ea027d29736e174 100644 (file)
@@ -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%%",
index 6a89f1ec0566a31e2f80ffa767e6b3094c071990..d913607fab8c3f8f5a32c63a76c02e67a38d2e77 100644 (file)
@@ -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 */
                                }
index b109d5b6da373bfe34279516b1609f8781e617e8..c4d51998bd5cef1bc966c5fb80a23b7f9d4d6f44 100644 (file)
@@ -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,
index e3364ddc829dd55ea36b9de9a9c9a082be7d1731..91d2317e3a25e0205ebed4c3a52f326dc55acace 100644 (file)
@@ -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 "
index d4ac8c47e99859cdb05012e1428a0b6164c8a572..ef2888f508d8e9e4aae81a9ee8f947b5cd390b22 100644 (file)
@@ -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;
+               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;
-                       return DM_PERCENT_INVALID;
+               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;
+               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;
-                       return DM_PERCENT_INVALID;
+               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 */
This page took 3.288817 seconds and 5 git commands to generate.