]> sourceware.org Git - lvm2.git/commitdiff
Account for mirror transient status when doing lvconvert --repair.
authorPetr Rockai <prockai@redhat.com>
Mon, 24 May 2010 15:32:20 +0000 (15:32 +0000)
committerPetr Rockai <prockai@redhat.com>
Mon, 24 May 2010 15:32:20 +0000 (15:32 +0000)
16 files changed:
lib/activate/activate.c
lib/activate/activate.h
lib/activate/dev_manager.c
lib/activate/dev_manager.h
lib/metadata/metadata-exported.h
lib/metadata/metadata.c
lib/metadata/metadata.h
lib/metadata/mirror.c
lib/metadata/segtype.h
lib/mirror/mirrored.c
test/t-lvconvert-repair-policy.sh
test/t-lvconvert-repair-transient.sh [new file with mode: 0644]
test/t-lvconvert-repair.sh
test/test-utils.sh
tools/lvconvert.c
tools/pvmove.c

index c6c6af7a834ba956947f4695b85fc772ca8abb23..2128c4198f733c94e1b97e69780e89a32431a007 100644 (file)
@@ -475,6 +475,28 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
        return r;
 }
 
+/*
+ * Returns 1 if percent set, else 0 on failure.
+ */
+int lv_check_transient(struct logical_volume *lv)
+{
+       int r;
+       struct dev_manager *dm;
+
+       if (!activation())
+               return 0;
+
+       if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
+               return_0;
+
+       if (!(r = dev_manager_transient(dm, lv)))
+               stack;
+
+       dev_manager_destroy(dm);
+
+       return r;
+}
+
 /*
  * Returns 1 if percent set, else 0 on failure.
  */
index cae962e5837ab94f20ea296646a2fdeb289e68f2..6a668fe80e11785e172ac2cec65ee9a892ce20f3 100644 (file)
@@ -78,6 +78,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
 int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
                         int *activate_lv);
 
+int lv_check_transient(struct logical_volume *lv);
 /*
  * Returns 1 if percent has been set, else 0.
  */
index f64560462835b04f7de22d47187217b6a4657f44..bdd403209d9bddbeb19b6ca621f68eb83315e699 100644 (file)
@@ -543,6 +543,68 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
        return 0;
 }
 
+int dev_manager_transient(struct dev_manager *dm, struct logical_volume *lv)
+{
+       int r = 0;
+       struct dm_task *dmt;
+       struct dm_info info;
+       void *next = NULL;
+       uint64_t start, length;
+       char *type = NULL;
+       char *params = NULL;
+       char *dlid = NULL;
+       const struct dm_list *segh = &lv->segments;
+       struct lv_segment *seg = NULL;
+
+       if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, NULL)))
+               return_0;
+
+       if (!(dmt = _setup_task(0, dlid, NULL, DM_DEVICE_STATUS, 0, 0)))
+               return_0;
+
+       if (!dm_task_no_open_count(dmt))
+               log_error("Failed to disable open_count");
+
+       if (!dm_task_run(dmt))
+               goto_out;
+
+       if (!dm_task_get_info(dmt, &info) || !info.exists)
+               goto_out;
+
+       do {
+               next = dm_get_next_target(dmt, next, &start, &length, &type,
+                                         &params);
+               if (lv) {
+                       if (!(segh = dm_list_next(&lv->segments, segh))) {
+                               log_error("Number of segments in active LV %s "
+                                         "does not match metadata", lv->name);
+                               goto out;
+                       }
+                       seg = dm_list_item(segh, struct lv_segment);
+               }
+
+               if (!type || !params)
+                       continue;
+
+               if (seg->segtype->ops->check_transient_status &&
+                   !seg->segtype->ops->check_transient_status(seg, params))
+                       goto_out;
+
+       } while (next);
+
+       if (lv && (segh = dm_list_next(&lv->segments, segh))) {
+               log_error("Number of segments in active LV %s does not "
+                         "match metadata", lv->name);
+               goto out;
+       }
+
+       r = 1;
+
+      out:
+       dm_task_destroy(dmt);
+       return r;
+}
+
 /*
  * dev_manager implementation.
  */
index e946aafb80bbe75574d710ebc83868d7c63393c2..614db859d8e31877d76ed895de6029b6e46a7160 100644 (file)
@@ -57,6 +57,7 @@ int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
 int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
                        int *flush_required);
 int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
+int dev_manager_transient(struct dev_manager *dm, struct logical_volume *lv);
 
 int dev_manager_mknodes(const struct logical_volume *lv);
 
index 258f221d57eafe74e4118cbd72febd322cf37db1..dbac0f2f5606513fc13cb819e5fa79869fd3247c 100644 (file)
@@ -754,7 +754,8 @@ int lv_split_mirror_images(struct logical_volume *lv, const char *split_lv_name,
                           uint32_t split_count, struct dm_list *removable_pvs);
 int lv_remove_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
                      uint32_t mirrors, uint32_t log_count,
-                     struct dm_list *pvs, uint64_t status_mask);
+                     int (*is_removable)(struct logical_volume *, void *),
+                     void *removable_baton, uint64_t status_mask);
 
 int is_temporary_mirror_layer(const struct logical_volume *lv);
 struct logical_volume * find_temporary_mirror(const struct logical_volume *lv);
@@ -769,7 +770,8 @@ int add_mirrors_to_segments(struct cmd_context *cmd, struct logical_volume *lv,
                            struct dm_list *allocatable_pvs, alloc_policy_t alloc);
 
 int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
-                        struct dm_list *removable_pvs, unsigned remove_log);
+                        int (*is_removable)(struct logical_volume *, void *),
+                        void *removable_baton, unsigned remove_log);
 int add_mirror_images(struct cmd_context *cmd, struct logical_volume *lv,
                      uint32_t mirrors, uint32_t stripes, uint32_t stripe_size, uint32_t region_size,
                      struct dm_list *allocatable_pvs, alloc_policy_t alloc,
index b49f975d5ae2a965d931cd558cd1d61271c7430b..d76a9102448effa174cd36e05ba2f33fdcde9394 100644 (file)
@@ -2117,7 +2117,7 @@ static int _lv_mark_if_partial(struct logical_volume *lv)
  * propagated transitively, so LVs referencing other LVs are marked
  * partial as well, if any of their referenced LVs are marked partial.
  */
-static int _vg_mark_partial_lvs(struct volume_group *vg)
+int vg_mark_partial_lvs(struct volume_group *vg)
 {
        struct logical_volume *lv;
        struct lv_list *lvl;
@@ -2654,7 +2654,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
                if (vg_missing_pv_count(correct_vg)) {
                        log_verbose("There are %d physical volumes missing.",
                                    vg_missing_pv_count(correct_vg));
-                       _vg_mark_partial_lvs(correct_vg);
+                       vg_mark_partial_lvs(correct_vg);
                }
                *consistent = 1;
                return correct_vg;
@@ -2945,7 +2945,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
        if (vg_missing_pv_count(correct_vg)) {
                log_verbose("There are %d physical volumes missing.",
                            vg_missing_pv_count(correct_vg));
-               _vg_mark_partial_lvs(correct_vg);
+               vg_mark_partial_lvs(correct_vg);
        }
 
        if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
index 7177070d5e839c53f1a3f7ac51f0fb667ce670f2..3a3979d8db15a687d1a895de505edc73f5f2d1af 100644 (file)
@@ -383,5 +383,7 @@ struct id pv_vgid(const struct physical_volume *pv);
 struct physical_volume *pv_by_path(struct cmd_context *cmd, const char *pv_name);
 int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
                 struct physical_volume *pv);
+int vg_mark_partial_lvs(struct volume_group *vg);
+int is_mirror_image_removable(struct logical_volume *mimage_lv, void *baton);
 
 #endif
index 7ea26d5f0abff0d648c043d0da2c491ddee74854..11777c0ed315daccf016e2ee4d89f640c0833b63 100644 (file)
@@ -435,14 +435,17 @@ struct logical_volume *detach_mirror_log(struct lv_segment *mirrored_seg)
 }
 
 /* Check if mirror image LV is removable with regard to given removable_pvs */
-static int _is_mirror_image_removable(struct logical_volume *mimage_lv,
-                                     struct dm_list *removable_pvs)
+int is_mirror_image_removable(struct logical_volume *mimage_lv, void *baton)
 {
        struct physical_volume *pv;
        struct lv_segment *seg;
        int pv_found;
        struct pv_list *pvl;
        uint32_t s;
+       struct dm_list *removable_pvs = baton;
+
+       if (!baton || dm_list_empty(removable_pvs))
+               return 1;
 
        dm_list_iterate_items(seg, &mimage_lv->segments) {
                for (s = 0; s < seg->area_count; s++) {
@@ -508,7 +511,7 @@ static int _move_removable_mimages_to_end(struct logical_volume *lv,
                        sub_lv = seg_lv(mirrored_seg, i);
 
                        if (!is_temporary_mirror_layer(sub_lv) &&
-                           _is_mirror_image_removable(sub_lv, removable_pvs)) {
+                           is_mirror_image_removable(sub_lv, removable_pvs)) {
                                if (!shift_mirror_images(mirrored_seg, i))
                                        return_0;
                                count--;
@@ -754,13 +757,13 @@ static int _split_mirror_images(struct logical_volume *lv,
  */
 static int _remove_mirror_images(struct logical_volume *lv,
                                 uint32_t num_removed,
-                                struct dm_list *removable_pvs,
+                                int (*is_removable)(struct logical_volume *, void *),
+                                void *removable_baton,
                                 unsigned remove_log, unsigned collapse,
                                 uint32_t *removed)
 {
        uint32_t m;
        int32_t s;
-       int removable_pvs_specified;
        struct logical_volume *sub_lv;
        struct logical_volume *detached_log_lv = NULL;
        struct logical_volume *temp_layer_lv = NULL;
@@ -770,9 +773,6 @@ static int _remove_mirror_images(struct logical_volume *lv,
        struct lv_list *lvl;
        struct dm_list tmp_orphan_lvs;
 
-       removable_pvs_specified = (removable_pvs &&
-                                  !dm_list_empty(removable_pvs)) ? 1 : 0;
-
        if (removed)
                *removed = 0;
 
@@ -781,38 +781,32 @@ static int _remove_mirror_images(struct logical_volume *lv,
                         old_area_count, old_area_count - num_removed,
                         remove_log ? " and no log volume" : "");
 
-       if (collapse &&
-           (removable_pvs_specified || (old_area_count - num_removed != 1))) {
+       if (collapse && (old_area_count - num_removed != 1)) {
                log_error("Incompatible parameters to _remove_mirror_images");
                return 0;
        }
 
        /* Move removable_pvs to end of array */
-       if (removable_pvs_specified) {
-               for (s = mirrored_seg->area_count - 1;
-                    s >= 0 && old_area_count - new_area_count < num_removed;
-                    s--) {
-                       sub_lv = seg_lv(mirrored_seg, s);
-
-                       if (!is_temporary_mirror_layer(sub_lv) &&
-                           _is_mirror_image_removable(sub_lv, removable_pvs)) {
-                               /*
-                                * Check if the user is trying to pull the
-                                * primary mirror image when the mirror is
-                                * not in-sync.
-                                */
-                               if ((s == 0) && !_mirrored_lv_in_sync(lv) &&
-                                   !(lv->status & PARTIAL_LV)) {
-                                       log_error("Unable to remove primary mirror image while mirror is not in-sync");
-                                       return_0;
-                               }
-                               if (!shift_mirror_images(mirrored_seg, s))
-                                       return_0;
-                               new_area_count--;
+       for (s = mirrored_seg->area_count - 1;
+            s >= 0 && old_area_count - new_area_count < num_removed;
+            s--) {
+               sub_lv = seg_lv(mirrored_seg, s);
+               if (!is_temporary_mirror_layer(sub_lv) &&
+                   is_removable(sub_lv, removable_baton)) {
+                       /*
+                        * Check if the user is trying to pull the
+                        * primary mirror image when the mirror is
+                        * not in-sync.
+                        */
+                       if ((s == 0) && !_mirrored_lv_in_sync(lv) &&
+                           !(lv->status & PARTIAL_LV)) {
+                               log_error("Unable to remove primary mirror image while mirror is not in-sync");
+                               return_0;
                        }
+                       if (!shift_mirror_images(mirrored_seg, s))
+                               return_0;
+                       new_area_count--;
                }
-               if (num_removed && old_area_count == new_area_count)
-                       return 1;
        }
 
        /*
@@ -822,6 +816,9 @@ static int _remove_mirror_images(struct logical_volume *lv,
         */
        new_area_count = old_area_count - num_removed;
 
+       if (num_removed && old_area_count == new_area_count)
+               return 1;
+
        /* Remove mimage LVs from the segment */
        dm_list_init(&tmp_orphan_lvs);
        for (m = new_area_count; m < mirrored_seg->area_count; m++) {
@@ -956,7 +953,8 @@ static int _remove_mirror_images(struct logical_volume *lv,
  * Remove the number of mirror images from the LV
  */
 int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
-                        struct dm_list *removable_pvs, unsigned remove_log)
+                        int (*is_removable)(struct logical_volume *, void *),
+                        void *removable_baton, unsigned remove_log)
 {
        uint32_t num_removed, removed_once, r;
        uint32_t existing_mirrors = lv_mirror_count(lv);
@@ -972,7 +970,8 @@ int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
                        removed_once = first_seg(next_lv)->area_count - 1;
 
                if (!_remove_mirror_images(next_lv, removed_once,
-                                          removable_pvs, remove_log, 0, &r))
+                                          is_removable, removable_baton,
+                                          remove_log, 0, &r))
                        return_0;
 
                if (r < removed_once) {
@@ -999,6 +998,11 @@ int remove_mirror_images(struct logical_volume *lv, uint32_t num_mirrors,
        return 1;
 }
 
+static int _no_removable_images(struct logical_volume *lv __attribute((unused)),
+                               void *baton __attribute((unused))) {
+       return 0;
+}
+
 /*
  * Collapsing temporary mirror layers.
  *
@@ -1031,7 +1035,7 @@ int collapse_mirrored_lv(struct logical_volume *lv)
 
                if (!_remove_mirror_images(mirror_seg->lv,
                                           mirror_seg->area_count - 1,
-                                          NULL, 1, 1, NULL)) {
+                                          _no_removable_images, NULL, 1, 1, NULL)) {
                        log_error("Failed to release mirror images");
                        return 0;
                }
@@ -1156,7 +1160,8 @@ int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirr
        init_mirror_in_sync(in_sync);
 
        r = _remove_mirror_images(mirrored_seg->lv, old_num_mirrors - num_mirrors,
-                                 removable_pvs, remove_log, 0, NULL);
+                                 is_mirror_image_removable, removable_pvs,
+                                 remove_log, 0, NULL);
        if (!r)
                /* Unable to remove bad devices */
                return 0;
@@ -1549,7 +1554,7 @@ int remove_mirror_log(struct cmd_context *cmd,
        }
 
        if (!remove_mirror_images(lv, lv_mirror_count(lv),
-                                 removable_pvs, 1U))
+                                 is_mirror_image_removable, removable_pvs, 1U))
                return_0;
 
        return 1;
@@ -1929,7 +1934,9 @@ int lv_split_mirror_images(struct logical_volume *lv, const char *split_name,
  */
 int lv_remove_mirrors(struct cmd_context *cmd __attribute((unused)),
                      struct logical_volume *lv,
-                     uint32_t mirrors, uint32_t log_count, struct dm_list *pvs,
+                     uint32_t mirrors, uint32_t log_count,
+                     int (*is_removable)(struct logical_volume *, void *),
+                     void *removable_baton,
                      uint64_t status_mask)
 {
        uint32_t new_mirrors;
@@ -1957,7 +1964,8 @@ int lv_remove_mirrors(struct cmd_context *cmd __attribute((unused)),
        if (seg_type(seg, 0) == AREA_LV &&
            seg_lv(seg, 0)->status & MIRROR_IMAGE)
                return remove_mirror_images(lv, new_mirrors + 1,
-                                           pvs, log_count ? 1U : 0);
+                                           is_removable, removable_baton,
+                                           log_count ? 1U : 0);
 
        /* MIRROR_BY_SEG */
        if (log_count) {
index 89e2e9884ebb8a1282fe72ad9496a5fcdfa0152e..d15df8bb72ef77cb784636018e85ab5b416ac1ac 100644 (file)
@@ -82,6 +82,7 @@ struct segtype_handler {
                                 struct dm_tree_node *node, uint64_t len,
                                 uint32_t *pvmove_mirror_count);
        int (*target_status_compatible) (const char *type);
+       int (*check_transient_status) (struct lv_segment *seg, char *params);
        int (*target_percent) (void **target_state,
                               percent_range_t *percent_range,
                               struct dm_pool * mem,
index ee0ee64957f6059d36f98e783d096a4177372ccb..69452ebd324cb54531ab8809ecb26d4abdde3683 100644 (file)
@@ -239,6 +239,117 @@ static int _mirrored_target_percent(void **target_state,
        return 1;
 }
 
+static int _mirrored_transient_status(struct lv_segment *seg, char *params)
+{
+       int i, j;
+       struct logical_volume *lv = seg->lv;
+       struct lvinfo info;
+       char *p = NULL;
+       char **args, **log_args;
+       struct logical_volume **images;
+       struct logical_volume *log;
+       int num_devs, log_argc;
+       int failed = 0;
+       char *status;
+
+       log_error("Mirrored transient status: \"%s\"", params);
+
+       /* number of devices */
+       if (!dm_split_words(params, 1, 0, &p))
+               return_0;
+
+       if (!(num_devs = atoi(p)))
+               return_0;
+
+       p += strlen(p) + 1;
+
+       if (num_devs > DEFAULT_MIRROR_MAX_IMAGES) {
+               log_error("Unexpectedly many (%d) mirror images in %s.",
+                         num_devs, lv->name);
+               return_0;
+       }
+
+       args = alloca((num_devs + 5) * sizeof(char *));
+       images = alloca(num_devs * sizeof(struct logical_volume *));
+
+       if (dm_split_words(p, num_devs + 4, 0, args) < num_devs + 4)
+               return_0;
+
+       log_argc = atoi(args[3 + num_devs]);
+       log_args = alloca(log_argc * sizeof(char *));
+
+       if (log_argc > 16) {
+               log_error("Unexpectedly many (%d) log arguments in %s.",
+                         log_argc, lv->name);
+               return_0;
+       }
+
+
+       if (dm_split_words(args[3 + num_devs] + strlen(args[3 + num_devs]) + 1,
+                          log_argc, 0, log_args) < log_argc)
+               return_0;
+
+       if (num_devs != seg->area_count) {
+               log_error("Active mirror has a wrong number of mirror images!");
+               log_error("Metadata says %d, kernel says %d.", seg->area_count, num_devs);
+               return_0;
+       }
+
+       if (!strcmp(log_args[0], "disk")) {
+               char buf[32];
+               log = first_seg(lv)->log_lv;
+               lv_info(lv->vg->cmd, log, &info, 0, 0);
+               log_debug("Found mirror log at %d:%d", info.major, info.minor);
+               sprintf(buf, "%d:%d", info.major, info.minor);
+               if (strcmp(buf, log_args[1])) {
+                       log_error("Mirror log mismatch. Metadata says %s, kernel says %s.",
+                                 buf, log_args[1]);
+                       return_0;
+               }
+               log_very_verbose("Status of log (%s): %s", buf, log_args[2]);
+               if (log_args[2][0] != 'A') {
+                       log->status |= PARTIAL_LV;
+                       ++failed;
+               }
+       }
+
+       for (i = 0; i < num_devs; ++i)
+               images[i] = NULL;
+
+       for (i = 0; i < seg->area_count; ++i) {
+               char buf[32];
+               lv_info(lv->vg->cmd, seg_lv(seg, i), &info, 0, 0);
+               log_debug("Found mirror leg at %d:%d", info.major, info.minor);
+               sprintf(buf, "%d:%d", info.major, info.minor);
+               for (j = 0; j < num_devs; ++j) {
+                       if (!strcmp(buf, args[j])) {
+                           log_debug("Match: metadata image %d matches kernel image %d", i, j);
+                           images[j] = seg_lv(seg, i);
+                       }
+               }
+       }
+
+       status = args[2 + num_devs];
+
+       for (i = 0; i < num_devs; ++i) {
+               if (!images[i]) {
+                       log_error("Failed to find image %d (%s).", i, args[i]);
+                       return_0;
+               }
+               log_very_verbose("Status of image %d: %c", i, status[i]);
+               if (status[i] != 'A') {
+                       images[i]->status |= PARTIAL_LV;
+                       ++failed;
+               }
+       }
+
+       /* update PARTIAL_LV flags across the VG */
+       if (failed)
+               vg_mark_partial_lvs(lv->vg);
+
+       return 1;
+}
+
 static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
                    struct dm_tree_node *node, uint32_t area_count, uint32_t region_size)
 {
@@ -564,6 +675,7 @@ static struct segtype_handler _mirrored_ops = {
        .add_target_line = _mirrored_add_target_line,
        .target_percent = _mirrored_target_percent,
        .target_present = _mirrored_target_present,
+       .check_transient_status = _mirrored_transient_status,
 #ifdef DMEVENTD
        .target_monitored = _target_monitored,
        .target_monitor_events = _target_monitor_events,
index 8ba2654e0ac5d15b16ebef42e6297ab3e839425d..1f3121590b42b7511ce2dfb8a4f3f2751ddbde6c 100644 (file)
@@ -32,40 +32,49 @@ lvcreate -m 1 -L 1 -n mirror $vg
 lvchange -a n $vg/mirror
 
 # Fail a leg of a mirror.
-disable_dev $dev1
+aux disable_dev $dev1
 lvchange --partial -a y $vg/mirror
 repair 'activation { mirror_image_fault_policy = "remove" }'
 check linear $vg mirror
-cleanup $dev1
+aux cleanup $dev1
 
 # Fail a leg of a mirror.
 # Expected result: Mirror (leg replaced)
-disable_dev $dev1
+aux disable_dev $dev1
 repair 'activation { mirror_image_fault_policy = "replace" }'
 check mirror $vg mirror
 lvs | grep mirror_mlog
-cleanup $dev1
+aux cleanup $dev1
 
 # Fail a leg of a mirror (use old name for policy specification)
 # Expected result: Mirror (leg replaced)
-disable_dev $dev1
+aux disable_dev $dev1
 repair 'activation { mirror_device_fault_policy = "replace" }'
 check mirror $vg mirror
 lvs | grep mirror_mlog
-cleanup $dev1
+aux cleanup $dev1
 
 # Fail a leg of a mirror w/ no available spare
 # Expected result: 2-way with corelog
-disable_dev $dev2 $dev4
+aux disable_dev $dev2 $dev4
 repair 'activation { mirror_image_fault_policy = "replace" }'
 check mirror $vg mirror
 lvs | not grep mirror_mlog
-cleanup $dev2 $dev4
+aux cleanup $dev2 $dev4
 
 # Fail the log device of a mirror w/ no available spare
 # Expected result: mirror w/ corelog
-disable_dev $dev3 $dev4
-lvconvert --repair --use-policies --config 'activation { mirror_image_fault_policy = "replace" }' $vg/mirror
+aux disable_dev $dev3 $dev4
+repair 'activation { mirror_image_fault_policy = "replace" }' $vg/mirror
 check mirror $vg mirror
 lvs | not grep mirror_mlog
+aux cleanup $dev3 $dev4
+
+# Fail the log device with a remove policy
+# Expected result: mirror w/ corelog
+lvchange -a y $vg/mirror
+aux disable_dev $dev3 $dev4
+repair 'activation { mirror_log_fault_policy = "remove" }'
+check mirror $vg mirror core
+lvs | not grep mirror_mlog
 cleanup $dev3 $dev4
diff --git a/test/t-lvconvert-repair-transient.sh b/test/t-lvconvert-repair-transient.sh
new file mode 100644 (file)
index 0000000..3d4fd1a
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+prepare_vg 5
+
+# fail multiple devices
+
+lvcreate -m 3 --ig -L 1 -n 4way $vg
+disable_dev $dev2 $dev4
+mkfs.ext3 $DM_DEV_DIR/$vg/4way
+enable_dev $dev2 $dev4
+echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out
+lvs -a -o +devices | not grep unknown
+vgreduce --removemissing $vg
+check mirror $vg 4way
+lvchange -a n $vg/4way
index b8902f516691e71b62c931d0b105c770dc9c1ca7..bce8b5359726580a01489bc170e2979b9f4321c7 100644 (file)
 
 . ./test-utils.sh
 
-prepare_vg 5
 
 # fail multiple devices
 
-lvcreate -m 3 --ig -L 1 -n 4way $vg
+aux prepare_vg 5
+lvcreate -m 3 --ig -L 1 -n 4way $vg $dev1 $dev2 $dev3 $dev4 $dev5:0
 disable_dev $dev2 $dev4
 echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out
 lvs -a -o +devices | not grep unknown
 vgreduce --removemissing $vg
 enable_dev $dev2 $dev4
-check mirror $vg 4way
-lvchange -a n $vg/4way
-
-vgremove -ff $vg
-vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4
+check mirror $vg 4way $dev5
 
+aux prepare_vg 5
 lvcreate -m 2 --ig -L 1 -n 3way $vg
 disable_dev $dev1 $dev2
 echo n | lvconvert --repair $vg/3way
+check linear $vg 3way
 lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+dmsetup ls | grep $PREFIX | not grep mlog
 vgreduce --removemissing $vg
 enable_dev $dev1 $dev2
 check linear $vg 3way
-lvchange -a n $vg/3way
+
+# fail just log and get it removed
+
+aux prepare_vg 5
+lvcreate -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4:0
+disable_dev $dev4
+echo n | lvconvert --repair $vg/3way
+check mirror $vg 3way core
+lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+dmsetup ls | grep $PREFIX | not grep mlog
+vgreduce --removemissing $vg
+enable_dev $dev4
+
+aux prepare_vg 5
+lvcreate -m 1 --ig -L 1 -n 2way $vg $dev1 $dev2 $dev3:0
+disable_dev $dev3
+echo n | lvconvert --repair $vg/2way
+check mirror $vg 2way core
+lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+vgreduce --removemissing $vg
+enable_dev $dev3
 
 # fail single devices
 
-vgremove -ff $vg
-vgcreate -c n $vg $dev1 $dev2 $dev3
+aux prepare_vg 5
+vgreduce $vg $dev4
 
 lvcreate -m 1 --ig -L 1 -n mirror $vg
-
 lvchange -a n $vg/mirror
 vgextend $vg $dev4
 disable_dev $dev1
index fd804b15ad0ff53db018dc92423e3fba69e0d134..16638d1250414d163afd6b1f0d366072a3af26ed 100644 (file)
@@ -373,6 +373,7 @@ prepare_lvmconf() {
     level = 9
     file = "$TESTDIR/debug.log"
     overwrite = 1
+    activation = 1
   }
   backup {
     backup = 0
index 86a0d7df5f9da6c3f7c2d0e18225cf426760cb99..0d602064278b0a8e3826a8e0cacf22ead5243fd1 100644 (file)
@@ -15,6 +15,7 @@
 #include "tools.h"
 #include "polldaemon.h"
 #include "lv_alloc.h"
+#include "metadata.h"
 
 struct lvconvert_params {
        int snapshot;
@@ -603,6 +604,12 @@ static struct dm_list *_failed_pv_list(struct volume_group *vg)
        return failed_pvs;
 }
 
+static int _is_partial_lv(struct logical_volume *lv,
+                         void *baton __attribute((unused)))
+{
+       return lv->status & PARTIAL_LV;
+}
+
 /*
  * Walk down the stacked mirror LV to the original mirror LV.
  */
@@ -727,7 +734,7 @@ static int _lv_update_log_type(struct cmd_context *cmd,
        }
 
        /* Reducing redundancy of the log */
-       return remove_mirror_images(log_lv, log_count, operable_pvs, 1U);
+       return remove_mirror_images(log_lv, log_count, is_mirror_image_removable, operable_pvs, 1U);
 }
 
 /*
@@ -913,6 +920,34 @@ static int _lvconvert_mirrors_parse_params(struct cmd_context *cmd,
        return 1;
 }
 
+static int _reload_lv(struct cmd_context *cmd, struct logical_volume *lv)
+{
+       log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
+
+       if (!vg_write(lv->vg))
+               return_0;
+
+       if (!suspend_lv(cmd, lv)) {
+               log_error("Failed to lock %s", lv->name);
+               vg_revert(lv->vg);
+               return 0;
+       }
+
+       if (!vg_commit(lv->vg)) {
+               if (!resume_lv(cmd, lv))
+                       stack;
+               return_0;
+       }
+
+       log_very_verbose("Updating \"%s\" in kernel", lv->name);
+
+       if (!resume_lv(cmd, lv)) {
+               log_error("Problem reactivating %s", lv->name);
+               return 0;
+       }
+       return 1;
+}
+
 /*
  * _lvconvert_mirrors_aux
  *
@@ -1004,6 +1039,16 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
                        return 0;
                }
 
+               /*
+                * Is there already a convert in progress?  We do not
+                * currently allow more than one.
+                */
+               if (find_temporary_mirror(lv) || (lv->status & CONVERTING)) {
+                       log_error("%s is already being converted.  Unable to start another conversion.",
+                                 lv->name);
+                       return 0;
+               }
+
                /*
                 * Log addition/removal should be done before the layer
                 * insertion to make the end result consistent with
@@ -1064,7 +1109,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
                                                    nmc, operable_pvs))
                                return 0;
                } else if (!lv_remove_mirrors(cmd, lv, nmc, nlc,
-                                             operable_pvs, 0))
+                                             is_mirror_image_removable, operable_pvs, 0))
                        return_0;
 
                goto out; /* Just in case someone puts code between */
@@ -1084,29 +1129,8 @@ out:
 
 out_skip_log_convert:
 
-       log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
-
-       if (!vg_write(lv->vg))
-               return_0;
-
-       if (!suspend_lv(cmd, lv)) {
-               log_error("Failed to lock %s", lv->name);
-               vg_revert(lv->vg);
-               goto out;
-       }
-
-       if (!vg_commit(lv->vg)) {
-               if (!resume_lv(cmd, lv))
-                       stack;
-               goto_out;
-       }
-
-       log_very_verbose("Updating \"%s\" in kernel", lv->name);
-
-       if (!resume_lv(cmd, lv)) {
-               log_error("Problem reactivating %s", lv->name);
-               goto out;
-       }
+       if (!_reload_lv(cmd, lv))
+               return 0;
 
        return 1;
 }
@@ -1139,6 +1163,8 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
        cmd->partial_activation = 1;
        lp->need_polling = 0;
 
+       lv_check_transient(lv); /* TODO check this in lib for all commands? */
+
        if (!(lv->status & PARTIAL_LV)) {
                log_error("%s is consistent. Nothing to repair.", lv->name);
                return 1;
@@ -1195,11 +1221,13 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
        if (!_lv_update_log_type(cmd, lp, lv, failed_pvs, new_log_count))
                return 0;
 
-       /*
-        * Remove all failed_pvs
-        */
-       if (!_lvconvert_mirrors_aux(cmd, lv, lp, failed_pvs,
-                                   lp->mirrors, new_log_count))
+       if (failed_mirrors) {
+               if (!lv_remove_mirrors(cmd, lv, failed_mirrors, new_log_count,
+                                      _is_partial_lv, NULL, 0))
+                       return 0;
+       }
+
+       if (!_reload_lv(cmd, lv))
                return 0;
 
        /*
@@ -1209,6 +1237,13 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
        if (replace_mirrors)
                lp->mirrors = old_mimage_count;
 
+       /*
+        * It does not make sense to replace the log if the volume is no longer
+        * a mirror.
+        */
+       if (!replace_mirrors && lp->mirrors == 1)
+               replace_log = 0;
+
        log_count = replace_log ? old_log_count : new_log_count;
 
        while (replace_mirrors || replace_log) {
@@ -1226,10 +1261,10 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
                }
        }
 
-       if (lp->mirrors != old_mimage_count)
+       if (replace_mirrors && lp->mirrors != old_mimage_count)
                log_warn("WARNING: Failed to replace %d of %d images in volume %s",
                         old_mimage_count - lp->mirrors, old_mimage_count, lv->name);
-       if (log_count != old_log_count)
+       if (replace_log && log_count != old_log_count)
                log_warn("WARNING: Failed to replace %d of %d logs in volume %s",
                         old_log_count - log_count, old_log_count, lv->name);
 
index f392de504f499f18d5e02e9266d31a166d3c3a32..2a3c27c6ead6ca9861d93e690e9ee4f0aa3a9a0e 100644 (file)
@@ -292,7 +292,7 @@ static int _detach_pvmove_mirror(struct cmd_context *cmd,
 
        /* Update metadata to remove mirror segments and break dependencies */
        dm_list_init(&lvs_completed);
-       if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, PVMOVE) ||
+       if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, NULL, NULL, PVMOVE) ||
            !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
                                            &lvs_completed)) {
                return 0;
This page took 0.065414 seconds and 5 git commands to generate.