int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
struct list *removable_pvs, int remove_log);
+int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+ struct list *removable_pvs, int remove_log);
/*
* Given mirror image or mirror log segment, find corresponding mirror segment
*/
return 1;
}
+int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
+ struct list *removable_pvs, int remove_log)
+{
+ int r;
+ int insync = 0;
+ int mirror_dev_failed = (mirrored_seg->area_count != num_mirrors);
+ float sync_percent = 0;
+
+ /* was the mirror in-sync before problems? */
+ if (!lv_mirror_percent(mirrored_seg->lv->vg->cmd,
+ mirrored_seg->lv, 0, &sync_percent, NULL))
+ log_error("Unable to determine mirror sync status.");
+ else if (sync_percent >= 100.0)
+ insync = 1;
+
+ /*
+ * While we are only removing devices, we can have sync set.
+ * Setting this is only useful if we are moving to core log
+ * otherwise the disk log will contain the sync information
+ */
+ init_mirror_in_sync(insync);
+
+ r = remove_mirror_images(mirrored_seg, num_mirrors,
+ removable_pvs, remove_log);
+ if (!r)
+ /* Unable to remove bad devices */
+ return 0;
+
+ return 1;
+}
+
static int _create_layers_for_mirror(struct alloc_handle *ah,
uint32_t first_area,
uint32_t num_mirrors,
struct lv_segment *seg, *mirrored_seg;
struct lv_segment_area area;
unsigned s;
- uint32_t mimages;
+ uint32_t mimages, remove_log;
int list_unsafe, only_mirror_images_found;
LIST_INIT(lvs_changed);
only_mirror_images_found = 1;
mirrored_seg = first_seg(lvl->lv);
if (!seg_is_mirrored(mirrored_seg))
continue;
+
mimages = mirrored_seg->area_count;
+ remove_log = 0;
+
for (s = 0; s < mirrored_seg->area_count; s++) {
list_iterate_items_safe(lvl2, lvlt, &lvs_changed) {
if (seg_type(mirrored_seg, s) != AREA_LV ||
mimages--; /* FIXME Assumes uniqueness */
}
}
- if (mimages != mirrored_seg->area_count) {
- if (!remove_mirror_images(mirrored_seg, mimages, NULL, 0)) {
+
+ if (mirrored_seg->log_lv) {
+ list_iterate_items(seg, &mirrored_seg->log_lv->segments) {
+ /* FIXME: The second test shouldn't be required */
+ if ((seg->segtype ==
+ get_segtype_from_string(vg->cmd, "error")) ||
+ (!strcmp(seg->segtype->name, "error"))) {
+ log_print("The log device for %s/%s has failed.",
+ vg->name, mirrored_seg->lv->name);
+ remove_log = 1;
+ break;
+ }
+ }
+ }
+
+ if ((mimages != mirrored_seg->area_count) || (remove_log)){
+ if (!reconfigure_mirror_images(mirrored_seg, mimages,
+ NULL, remove_log)) {
stack;
return 0;
}
/* Deactivate error LVs */
if (!test_mode()) {
- list_iterate_items(lvl, &lvs_changed) {
+ list_iterate_items_safe(lvl, lvlt, &lvs_changed) {
log_verbose("Deactivating (if active) logical volume %s",
lvl->lv->name);
if (!deactivate_lv(cmd, lvl->lv)) {
log_error("Failed to deactivate LV %s",
lvl->lv->name);
- return 0;
+ /*
+ * We failed to deactivate.
+ * Probably because this was a mirror log.
+ * Don't try to lv_remove it.
+ * Continue work on others.
+ */
+ list_del(&lvl->list);
}
}
}