diff --git a/WHATS_NEW b/WHATS_NEW index 264a0b9ad..5c8f49c2f 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.01.11 - ============================== + Allow mirror images to be resized. Allow mirror images to have more than one segment. Centralise restrictions on LV names. Always insert an intermediate layer for mirrors. diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 3dab5dc46..4b33cb1bf 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -300,7 +300,7 @@ static struct alloc_handle *_alloc_init(struct pool *mem, uint32_t s, area_count; if (stripes > 1 && mirrors > 1) { - log_error("striped mirrors are not supported yet"); + log_error("Striped mirrors are not supported yet"); return NULL; } @@ -980,7 +980,9 @@ int lv_extend(struct logical_volume *lv, alloc_policy_t alloc) { int r = 1; + uint32_t m; struct alloc_handle *ah; + struct lv_segment *first_seg; if (segtype_is_virtual(segtype)) return lv_add_virtual_segment(lv, status, extents, segtype); @@ -992,10 +994,29 @@ int lv_extend(struct logical_volume *lv, return 0; } - if (!lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size, + if (!mirrors) { + if (!lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size, mirrored_pv, mirrored_pe, status, 0, NULL)) { - stack; - goto out; + stack; + goto out; + } + } else { + list_iterate_items(first_seg, &lv->segments) + break; + for (m = 0; m < mirrors; m++) { + if (!lv_add_segment(ah, m, 1, seg_lv(first_seg, m), + get_segtype_from_string(lv->vg->cmd, + "striped"), + 0, NULL, 0, 0, 0, NULL)) { + log_error("Aborting. Failed to extend %s.", + seg_lv(first_seg, m)->name); + return 0; + } + } + first_seg->area_len += extents; + first_seg->len += extents; + lv->le_count += extents; + lv->size += (uint64_t) extents *lv->vg->extent_size; } out: diff --git a/tools/commands.h b/tools/commands.h index 6b2246494..42d591822 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -178,6 +178,7 @@ xx(lvextend, "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n" "\t{-l|--extents [+]LogicalExtentsNumber |\n" "\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n" + "\t[-m|--mirrors Mirrors]\n" "\t[-n|--nofsck]\n" "\t[-r|--resizefs]\n" "\t[-t|--test]\n" @@ -186,8 +187,9 @@ xx(lvextend, "\t[--version]" "\n" "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n", - alloc_ARG, autobackup_ARG, extents_ARG, nofsck_ARG, resizefs_ARG, - size_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG) + alloc_ARG, autobackup_ARG, extents_ARG, mirrors_ARG, nofsck_ARG, + resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG, test_ARG, + type_ARG) xx(lvmchange, "With the device mapper, this is obsolete and does nothing.", diff --git a/tools/lvcreate.c b/tools/lvcreate.c index b495060ba..17e2bf68e 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -497,6 +497,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) return 0; } + if (lp->mirrors && !(vg->fid->fmt->features & FMT_SEGMENTS)) { + log_error("Metadata does not support mirroring."); + return 0; + } + /* * Create the pv list. */ diff --git a/tools/lvresize.c b/tools/lvresize.c index ad3c29c00..e2eb15c7a 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -23,6 +23,7 @@ struct lvresize_params { uint32_t stripes; uint32_t stripe_size; + uint32_t mirrors; struct segment_type *segtype; @@ -119,6 +120,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) struct lvinfo info; uint32_t stripesize_extents = 0; uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0; + uint32_t seg_mirrors = 0; uint32_t extents_used = 0; uint32_t size_rest; alloc_policy_t alloc; @@ -161,6 +163,13 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) log_print("Varied striping not supported. Ignoring."); } + if (arg_count(cmd, mirrors_ARG)) { + if (vg->fid->fmt->features & FMT_SEGMENTS) + lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1; + else + log_print("Mirrors not supported. Ignoring."); + } + if (arg_count(cmd, stripesize_ARG)) { if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) { log_error("Stripesize may not be negative."); @@ -171,6 +180,10 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) stripesize_ARG, 0); else log_print("Varied stripesize not supported. Ignoring."); + if (lp->mirrors) { + log_error("Mirrors and striping cannot be combined yet."); + return ECMD_FAILED; + } } lv = lvl->lv; @@ -277,13 +290,34 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) } } + /* If extending, find mirrors of last segment */ + if ((lp->extents > lv->le_count)) { + list_iterate_back_items(seg, &lv->segments) { + if (seg_is_mirrored(seg)) + seg_mirrors = seg->area_count; + else + seg_mirrors = 0; + break; + } + if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) { + log_print("Extending %" PRIu32 " mirror images.", + seg_mirrors); + lp->mirrors = seg_mirrors; + } + if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) && + (lp->mirrors != seg_mirrors)) { + log_error("Cannot vary number of mirrors in LV yet."); + return EINVALID_CMD_LINE; + } + } + /* If reducing, find stripes, stripesize & size of last segment */ if (lp->extents < lv->le_count) { extents_used = 0; - if (lp->stripes || lp->stripe_size) - log_error("Ignoring stripes and stripesize arguments " - "when reducing"); + if (lp->stripes || lp->stripe_size || lp->mirrors) + log_error("Ignoring stripes, stripesize and mirrors " + "arguments when reducing"); list_iterate_items(seg, &lv->segments) { seg_extents = seg->len; @@ -293,6 +327,11 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) seg_stripes = seg->area_count; } + if (seg_is_mirrored(seg)) + seg_mirrors = seg->area_count; + else + seg_mirrors = 0; + if (lp->extents <= extents_used + seg_extents) break; @@ -302,6 +341,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) seg_size = lp->extents - extents_used; lp->stripe_size = seg_stripesize; lp->stripes = seg_stripes; + lp->mirrors = seg_mirrors; } if (lp->stripes > 1 && !lp->stripe_size) { @@ -456,7 +496,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) return ECMD_FAILED; } } else if (!lv_extend(lv, lp->segtype, lp->stripes, - lp->stripe_size, 0u, + lp->stripe_size, lp->mirrors, lp->extents - lv->le_count, NULL, 0u, 0u, pvh, alloc)) { stack;