From 532dae4854e8dd118bdc24615df875d054610b84 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Thu, 11 May 2006 19:01:11 +0000 Subject: [PATCH] Allow vgreduce to handle mirror log failures. --- WHATS_NEW | 1 + lib/metadata/metadata.h | 2 ++ lib/metadata/mirror.c | 31 +++++++++++++++++++++++++++++++ tools/vgreduce.c | 35 ++++++++++++++++++++++++++++++----- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index d88faed93..4e63dafa1 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.06 - ================================= + Allow vgreduce to handle mirror log failures. Add --corelog to lvcreate and lvconvert. Create a log header for replacement in-sync mirror log. Use set_lv() and dev_set() to wipe sections of devices. diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 1673fd833..ade86c70c 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -580,6 +580,8 @@ int add_mirror_layers(struct alloc_handle *ah, 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 */ diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c index 84809d897..04bb9fa9a 100644 --- a/lib/metadata/mirror.c +++ b/lib/metadata/mirror.c @@ -230,6 +230,37 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors, 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, diff --git a/tools/vgreduce.c b/tools/vgreduce.c index c0f70aaf5..c637aaccd 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -158,7 +158,7 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg) 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; @@ -259,7 +259,10 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg) 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 || @@ -272,8 +275,24 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg) 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; } @@ -295,14 +314,20 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg) /* 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); } } }