diff --git a/WHATS_NEW b/WHATS_NEW index c4c65c5f9..516d7d21b 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.54 - ===================================== + Permit snapshots of mirrors. Cleanup mimagetmp LV if allocation fails for new lvconvert mimage. Fix clvmd segfault when refresh_toolcontext fails. Remember to clear 'global lock held during cache refresh' state after use. diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 05a5a56e4..ea8f1d173 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -551,16 +551,17 @@ int dev_manager_mirror_percent(struct dev_manager *dm, { char *name; const char *dlid; + const char *suffix = (lv_is_origin(lv)) ? "real" : NULL; /* * Build a name for the top layer. */ - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) + if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, suffix))) return_0; /* FIXME dm_pool_free ? */ - if (!(dlid = build_dlid(dm, lv->lvid.s, NULL))) { + if (!(dlid = build_dlid(dm, lv->lvid.s, suffix))) { log_error("dlid build failed for %s", lv->name); return 0; } diff --git a/lib/display/display.c b/lib/display/display.c index 08c251854..52777435b 100644 --- a/lib/display/display.c +++ b/lib/display/display.c @@ -480,7 +480,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct lvinfo info; int inkernel, snap_active = 0; char uuid[64] __attribute((aligned(8))); - struct lv_segment *snap_seg = NULL; + struct lv_segment *snap_seg = NULL, *mirror_seg = NULL; float snap_percent; /* fused, fsize; */ percent_range_t percent_range; @@ -563,6 +563,13 @@ int lvdisplay_full(struct cmd_context *cmd, display_size(cmd, (uint64_t) snap_seg->chunk_size)); } + if (lv->status & MIRRORED) { + mirror_seg = first_seg(lv); + log_print("Mirrored volumes %" PRIu32, mirror_seg->area_count); + if (lv->status & CONVERTING) + log_print("LV type Mirror undergoing conversion"); + } + log_print("Segments %u", dm_list_size(&lv->segments)); /********* FIXME Stripes & stripesize for each segment diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 7bcd64fed..5041fd8e8 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -2936,11 +2936,12 @@ int lv_create_single(struct volume_group *vg, "supported yet"); return 0; } - if (org->status & MIRROR_IMAGE || - org->status & MIRROR_LOG || - org->status & MIRRORED) { - log_error("Snapshots and mirrors may not yet " - "be mixed."); + if ((org->status & MIRROR_IMAGE) || + (org->status & MIRROR_LOG)) { + log_error("Snapshots of mirror %ss " + "are not supported", + (org->status & MIRROR_LOG) ? + "log" : "image"); return 0; } diff --git a/lib/report/report.c b/lib/report/report.c index 2027af7b6..6262af245 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -311,6 +311,11 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_ repstr[0] = 'p'; else if (lv->status & CONVERTING) repstr[0] = 'c'; + else if (lv->status & VIRTUAL) + repstr[0] = 'v'; + /* Origin takes precedence over Mirror */ + else if (lv_is_origin(lv)) + repstr[0] = 'o'; else if (lv->status & MIRRORED) { if (lv->status & MIRROR_NOTSYNCED) repstr[0] = 'M'; @@ -323,10 +328,6 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_ repstr[0] = 'I'; else if (lv->status & MIRROR_LOG) repstr[0] = 'l'; - else if (lv->status & VIRTUAL) - repstr[0] = 'v'; - else if (lv_is_origin(lv)) - repstr[0] = 'o'; else if (lv_is_cow(lv)) repstr[0] = 's'; else diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 7a3e7abe6..1ec28bcea 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -713,6 +713,20 @@ static int _lvconvert_mirrors(struct cmd_context *cmd, struct logical_volume *lv "LV: use lvchange --resync first."); return 0; } + + /* + * We allow snapshots of mirrors, but for now, we + * do not allow up converting mirrors that are under + * snapshots. The layering logic is somewhat complex, + * and preliminary test show that the conversion can't + * seem to get the correct %'age of completion. + */ + if (lv_is_origin(lv)) { + log_error("Can't add additional mirror images to " + "mirrors that are under snapshots"); + return 0; + } + /* * Log addition/removal should be done before the layer * insertion to make the end result consistent with @@ -891,12 +905,6 @@ static int lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv, return ECMD_FAILED; } - if (lv_is_origin(lv)) { - log_error("Can't convert logical volume \"%s\" under snapshot", - lv->name); - return ECMD_FAILED; - } - if (lv_is_cow(lv)) { log_error("Can't convert snapshot logical volume \"%s\"", lv->name); diff --git a/tools/vgsplit.c b/tools/vgsplit.c index c00561bb6..42a176950 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -411,14 +411,15 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) if (!(_move_lvs(vg_from, vg_to))) goto_bad; - /* Move required snapshots across */ - if (!(_move_snapshots(vg_from, vg_to))) - goto_bad; - + /* FIXME Separate the 'move' from the 'validation' to fix dev stacks */ /* Move required mirrors across */ if (!(_move_mirrors(vg_from, vg_to))) goto_bad; + /* Move required snapshots across */ + if (!(_move_snapshots(vg_from, vg_to))) + goto_bad; + /* Split metadata areas and check if both vgs have at least one area */ if (!(vg_split_mdas(cmd, vg_from, vg_to)) && vg_from->pv_count) { log_error("Cannot split: Nowhere to store metadata for new Volume Group");