]> sourceware.org Git - lvm2.git/commitdiff
metadata: add historical_glv_remove
authorPeter Rajnoha <prajnoha@redhat.com>
Tue, 1 Mar 2016 14:26:57 +0000 (15:26 +0100)
committerPeter Rajnoha <prajnoha@redhat.com>
Thu, 3 Mar 2016 12:50:57 +0000 (13:50 +0100)
lib/format_text/import_vsn1.c
lib/metadata/lv_manip.c
lib/metadata/metadata-exported.h
lib/metadata/metadata.c
lib/metadata/vg.c
lib/metadata/vg.h

index 163ea38e59c7e6b4cc81668a2653b550d4ac7b61..3bf5f7b77cc4b1dac4383fe045b09690f11bc44e 100644 (file)
@@ -788,7 +788,7 @@ static int _read_historical_lvnames_interconnections(struct format_instance *fid
        historical_lv_name = hlvn->key;
        hlvn = hlvn->child;
 
-       if (!(glv = find_historical_glv(vg, historical_lv_name, NULL))) {
+       if (!(glv = find_historical_glv(vg, historical_lv_name, 0, NULL))) {
                log_error("Unknown historical logical volume %s/%s%s",
                          vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
                goto bad;
@@ -828,7 +828,7 @@ static int _read_historical_lvnames_interconnections(struct format_instance *fid
                glvl->glv = glv;
 
                if (!strncmp(origin_name, HISTORICAL_LV_PREFIX, strlen(HISTORICAL_LV_PREFIX))) {
-                       if (!(origin_glv = find_historical_glv(vg, origin_name + strlen(HISTORICAL_LV_PREFIX), NULL))) {
+                       if (!(origin_glv = find_historical_glv(vg, origin_name + strlen(HISTORICAL_LV_PREFIX), 0, NULL))) {
                                log_error("Unknown origin %s for historical logical volume %s/%s%s",
                                          origin_name, vg->name, HISTORICAL_LV_PREFIX, historical_lv_name);
                                goto bad;
index e355cc4a97b1ad4231c4b0f874ef9cadd7005869..c612873617e326b5661f8edc0d78d8e66f025315 100644 (file)
@@ -1398,11 +1398,75 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
        return _lv_reduce(lv, extents, 1);
 }
 
+int historical_glv_remove(struct generic_logical_volume *glv)
+{
+       struct generic_logical_volume *origin_glv;
+       struct glv_list *glvl, *user_glvl;
+       struct historical_logical_volume *hlv;
+       int reconnected;
+
+       if (!glv || !glv->is_historical)
+               return_0;
+
+       hlv = glv->historical;
+
+       if (!(glv = find_historical_glv(hlv->vg, hlv->name, 0, &glvl))) {
+               if (!(find_historical_glv(hlv->vg, hlv->name, 1, NULL))) {
+                       log_error(INTERNAL_ERROR "historical_glv_remove: historical LV %s/-%s not found ",
+                                 hlv->vg->name, hlv->name);
+                       return 0;
+               } else {
+                       log_verbose("Historical LV %s/-%s already on removed list ",
+                                   hlv->vg->name, hlv->name);
+                       return 1;
+               }
+       }
+
+       if ((origin_glv = hlv->indirect_origin) &&
+           !remove_glv_from_indirect_glvs(origin_glv, glv))
+               return_0;
+
+       dm_list_iterate_items(user_glvl, &hlv->indirect_glvs) {
+               reconnected = 0;
+               if ((origin_glv && !origin_glv->is_historical) && !user_glvl->glv->is_historical)
+                       log_verbose("Removing historical connection between %s and %s.",
+                                    origin_glv->live->name, user_glvl->glv->live->name);
+               else if (hlv->vg->cmd->record_historical_lvs) {
+                       if (!add_glv_to_indirect_glvs(hlv->vg->vgmem, origin_glv, user_glvl->glv))
+                               return_0;
+                       reconnected = 1;
+               }
+
+               if (!reconnected) {
+                       /*
+                        * Break ancestry chain if we're removing historical LV and tracking
+                        * historical LVs is switched off either via:
+                        *   - "metadata/record_lvs_history=0" config
+                        *   - "--nohistory" cmd line option
+                        *
+                        * Also, break the chain if we're unable to store such connection at all
+                        * because we're removing the very last historical LV that was in between
+                        * live LVs - pure live LVs can't store any indirect origin relation in
+                        * metadata - we need at least one historical LV to do that!
+                        */
+                       if (user_glvl->glv->is_historical)
+                               user_glvl->glv->historical->indirect_origin = NULL;
+                       else
+                               first_seg(user_glvl->glv->live)->indirect_origin = NULL;
+               }
+       }
+
+       dm_list_move(&hlv->vg->removed_historical_lvs, &glvl->list);
+       return 1;
+}
+
 /*
  * Completely remove an LV.
  */
 int lv_remove(struct logical_volume *lv)
 {
+       if (lv_is_historical(lv))
+               return historical_glv_remove(lv->this_glv);
 
        if (!lv_reduce(lv, lv->le_count))
                return_0;
@@ -5740,9 +5804,9 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
                is_last_pool = 1;
        }
 
-       /* Used cache pool or COW cannot be activated */
+       /* Used cache pool, COW or historical LV cannot be activated */
        if ((!lv_is_cache_pool(lv) || dm_list_empty(&lv->segs_using_this_lv)) &&
-           !lv_is_cow(lv) &&
+           !lv_is_cow(lv) && !lv_is_historical(lv) &&
            !deactivate_lv(cmd, lv)) {
                /* FIXME Review and fix the snapshot error paths! */
                log_error("Unable to deactivate logical volume %s.",
index b8699f7aa02ba7d32d88b7264a413eccb182b0f8..d81166d4f993a2fbf7e28b357aea3c49a8c20acb 100644 (file)
@@ -807,6 +807,9 @@ int lv_extend(struct logical_volume *lv,
 /* lv must be part of lv->vg->lvs */
 int lv_remove(struct logical_volume *lv);
 
+/* historical_glv must be part of lv->vg->historical_lvs */
+int historical_glv_remove(struct generic_logical_volume *historical_glv);
+
 int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
                     force_t force, int suppress_remove_message);
 
@@ -1029,6 +1032,7 @@ struct logical_volume *find_lv(const struct volume_group *vg,
 
 struct generic_logical_volume *find_historical_glv(const struct volume_group *vg,
                                                    const char *historical_lv_name,
+                                                   int check_removed_list,
                                                    struct glv_list **glvl_found);
 
 struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
index 8b3c53c1bd9ae862b1b3e0eef325a637055e6333..c37c7ba02718fb9ca332a34a64f2f5491be5a372 100644 (file)
@@ -2122,10 +2122,13 @@ struct logical_volume *find_lv(const struct volume_group *vg,
 
 struct generic_logical_volume *find_historical_glv(const struct volume_group *vg,
                                               const char *historical_lv_name,
+                                              int check_removed_list,
                                               struct glv_list **glvl_found)
 {
        struct glv_list *glvl;
        const char *ptr;
+       const struct dm_list *list = check_removed_list ? &vg->removed_historical_lvs
+                                                       : &vg->historical_lvs;
 
        /* Use last component */
        if ((ptr = strrchr(historical_lv_name, '/')))
@@ -2133,7 +2136,7 @@ struct generic_logical_volume *find_historical_glv(const struct volume_group *vg
        else
                ptr = historical_lv_name;
 
-       dm_list_iterate_items(glvl, &vg->historical_lvs) {
+       dm_list_iterate_items(glvl, list) {
                if (!strcmp(glvl->glv->historical->name, ptr)) {
                        if (glvl_found)
                                *glvl_found = glvl;
index 90c459e191ab8df603dd35d903398e3ca638ee77..7ac1a2ca260ba82f971da7e3f71d874477ff2560 100644 (file)
@@ -67,6 +67,7 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
        dm_list_init(&vg->historical_lvs);
        dm_list_init(&vg->tags);
        dm_list_init(&vg->removed_lvs);
+       dm_list_init(&vg->removed_historical_lvs);
        dm_list_init(&vg->removed_pvs);
 
        log_debug_mem("Allocated VG %s at %p.", vg->name, vg);
index c5197cb3313f07d93f0335bb603b77c3b08df58b..069cdc8d284cb9437847be9d9d03b52336283a29 100644 (file)
@@ -141,6 +141,11 @@ struct volume_group {
         */
        struct dm_list removed_lvs;
 
+       /*
+        * List of removed historical logical volumes by historical_glv_remove.
+        */
+       struct dm_list removed_historical_lvs;
+
        /*
         * List of removed physical volumes by pvreduce.
         * They have to get cleared on vg_commit.
This page took 0.056487 seconds and 5 git commands to generate.