mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
thin: lvresize supports pool metadata resize
Add support for lvresize of thin pool metadata device. lvresize --poolmetadatasize +20 vgname/thinpool_lv or lvresize -L +20 vgname/thinpool_lv_tmeta Where the second one allows all the args for resize (striping...) and the first option resizes accoding to the last metadata lv segment.
This commit is contained in:
parent
72c3ae253e
commit
87aca628d6
@ -1,5 +1,6 @@
|
||||
Version 2.02.99 -
|
||||
===================================
|
||||
Add lvresize support for online thin pool metadata volume resize.
|
||||
Add helper functions find_pool_lv() and pool_can_resize_metadata().
|
||||
Add detection for thin pool metadata resize kernel support.
|
||||
Report lvs volume type 'e' with higher priority.
|
||||
|
@ -61,7 +61,7 @@ lvcreate \- create a logical volume in an existing volume group
|
||||
.RB [ \-\-discards
|
||||
.RI { ignore | nopassdown | passdown }]
|
||||
.RB [ \-\-poolmetadatasize
|
||||
.IR ThinPoolMetadataSize [ bBsSkKmMgG ]]]
|
||||
.IR MetadataVolumeSize [ bBsSkKmMgG ]]]
|
||||
.RB [ \-\-thinpool
|
||||
.IR ThinPoolLogicalVolume { Name | Path }
|
||||
.RB [ \-s | \-\-snapshot
|
||||
@ -271,7 +271,7 @@ Sets access permissions to read only (\fIr\fP) or read and write (\fIrw\fP).
|
||||
.br
|
||||
Default is read and write.
|
||||
.TP
|
||||
.IR \fB\-\-poolmetadatasize " " ThinPoolMetadataSize [ bBsSkKmMgG ]
|
||||
.IR \fB\-\-poolmetadatasize " " MetadataVolumeSize [ bBsSkKmMgG ]
|
||||
Sets the size of thin pool's metadata logical volume.
|
||||
Supported values are in range between 2MiB and 16GiB.
|
||||
Default value is (Pool_LV_size / Pool_LV_chunk_size * 64b).
|
||||
|
@ -11,6 +11,8 @@ lvresize \- resize a logical volume
|
||||
.RI [ + | \- ] LogicalExtentsNumber [ % { VG | LV | PVS | FREE | ORIGIN "}] |"
|
||||
.RB [ \-L | \-\-size
|
||||
.RI [ + | \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]}
|
||||
.RB [ \-\-poolmetadatasize
|
||||
.RI [ + ] MetadataVolumeSize [ bBsSkKmMgG ]
|
||||
.RB [ \-f | \-\-force ]
|
||||
.RB [ \-n | \-\-nofsck ]
|
||||
.RB [ \-r | \-\-resizefs ]
|
||||
@ -73,6 +75,13 @@ Defaults to whatever the last segment of the Logical Volume uses.
|
||||
Not applicable to LVs using the original metadata LVM format, which must
|
||||
use a single value throughout.
|
||||
.TP
|
||||
.IR \fB\-\-poolmetadatasize " [" + ] MetadataVolumeSize [ bBsSkKmMgG ]
|
||||
Change or set the thin pool metadata logical volume size.
|
||||
With the \fI+\fP sign the value is added to the actual size
|
||||
of the metadata volume and rounded to the full extent size
|
||||
and without it, the value is taken as an absolute one.
|
||||
Maximal size is 16GiB. Default unit is megabytes.
|
||||
.TP
|
||||
.BR \-I ", " \-\-stripesize " " \fIStripeSize
|
||||
Gives the number of kilobytes for the granularity of the stripes.
|
||||
Defaults to whatever the last segment of the Logical Volume uses.
|
||||
|
@ -233,7 +233,7 @@ xx(lvcreate,
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents LogicalExtentsNumber[%{VG|FREE|ORIGIN}] |\n"
|
||||
"\t -L|--size LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
|
||||
"\t[--poolmetadatasize Size[bBsSkKmMgG]]\n"
|
||||
"\t[--poolmetadatasize MetadataVolumeSize[bBsSkKmMgG]]\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
"\t[--noudevsync]\n"
|
||||
@ -308,6 +308,7 @@ xx(lvextend,
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE|ORIGIN}] |\n"
|
||||
"\t -L|--size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
|
||||
"\t --poolmetadatasize [+]MetadataVolumeSize[bBsSkKmMgG]}\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[--nosync]\n"
|
||||
"\t[--use-policies]\n"
|
||||
@ -321,7 +322,8 @@ xx(lvextend,
|
||||
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
||||
|
||||
alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, mirrors_ARG,
|
||||
nofsck_ARG, nosync_ARG, noudevsync_ARG, resizefs_ARG, size_ARG, stripes_ARG,
|
||||
nofsck_ARG, nosync_ARG, noudevsync_ARG, poolmetadatasize_ARG,
|
||||
resizefs_ARG, size_ARG, stripes_ARG,
|
||||
stripesize_ARG, test_ARG, type_ARG, use_policies_ARG)
|
||||
|
||||
xx(lvmchange,
|
||||
@ -437,6 +439,7 @@ xx(lvresize,
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|PVS|FREE|ORIGIN}] |\n"
|
||||
"\t -L|--size [+|-]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
|
||||
"\t --poolmetadatasize [+]MetadataVolumeSize[bBsSkKmMgG]}\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[--noudevsync]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
@ -447,7 +450,8 @@ xx(lvresize,
|
||||
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
|
||||
|
||||
alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, nofsck_ARG,
|
||||
noudevsync_ARG, resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG,
|
||||
noudevsync_ARG, resizefs_ARG, poolmetadatasize_ARG,
|
||||
size_ARG, stripes_ARG, stripesize_ARG,
|
||||
test_ARG, type_ARG)
|
||||
|
||||
xx(lvs,
|
||||
|
151
tools/lvresize.c
151
tools/lvresize.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -30,7 +30,10 @@ struct lvresize_params {
|
||||
/* size */
|
||||
uint32_t extents;
|
||||
uint64_t size;
|
||||
int sizeargs;
|
||||
sign_t sign;
|
||||
uint64_t poolmetadatasize;
|
||||
sign_t poolmetadatasign;
|
||||
percent_type_t percent;
|
||||
|
||||
enum {
|
||||
@ -192,6 +195,7 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
|
||||
int use_policy = arg_count(cmd, use_policies_ARG);
|
||||
|
||||
lp->sign = SIGN_NONE;
|
||||
lp->poolmetadatasign = SIGN_NONE;
|
||||
lp->resize = LV_ANY;
|
||||
|
||||
cmd_name = command_name(cmd);
|
||||
@ -211,13 +215,14 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
|
||||
* one or more PVs. Most likely, the intent was "resize this
|
||||
* LV the best you can with these PVs"
|
||||
*/
|
||||
if ((arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) == 0) &&
|
||||
(argc >= 2)) {
|
||||
lp->sizeargs = arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG);
|
||||
if ((lp->sizeargs == 0) && (argc >= 2)) {
|
||||
lp->extents = 100;
|
||||
lp->percent = PERCENT_PVS;
|
||||
lp->sign = SIGN_PLUS;
|
||||
} else if ((arg_count(cmd, extents_ARG) +
|
||||
arg_count(cmd, size_ARG) != 1)) {
|
||||
} else if ((lp->sizeargs != 1) &&
|
||||
((lp->sizeargs == 2) ||
|
||||
!arg_count(cmd, poolmetadatasize_ARG))) {
|
||||
log_error("Please specify either size or extents but not "
|
||||
"both.");
|
||||
return 0;
|
||||
@ -235,6 +240,15 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
|
||||
lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
|
||||
lp->percent = PERCENT_NONE;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, poolmetadatasize_ARG)) {
|
||||
lp->poolmetadatasize = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
|
||||
lp->poolmetadatasign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
|
||||
if (lp->poolmetadatasign == SIGN_MINUS) {
|
||||
log_error("Can't reduce pool metadata size.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
|
||||
@ -242,7 +256,8 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lp->resize == LV_REDUCE && lp->sign == SIGN_PLUS) {
|
||||
if (lp->resize == LV_REDUCE &&
|
||||
((lp->sign == SIGN_PLUS) || (lp->poolmetadatasign == SIGN_PLUS))) {
|
||||
log_error("Positive sign not permitted - use lvextend");
|
||||
return 0;
|
||||
}
|
||||
@ -306,18 +321,23 @@ static int _adjust_policy_params(struct cmd_context *cmd,
|
||||
if (lv_is_thin_pool(lv)) {
|
||||
if (!lv_thin_pool_percent(lv, 1, &percent))
|
||||
return_0;
|
||||
if (percent > policy_threshold) {
|
||||
/* FIXME: metadata resize support missing */
|
||||
log_error("Resize for %s/%s is not yet supported.",
|
||||
lp->vg_name, lp->lv_name);
|
||||
return ECMD_FAILED;
|
||||
if ((PERCENT_0 < percent && percent <= PERCENT_100) &&
|
||||
(percent > policy_threshold)) {
|
||||
if (!pool_can_resize_metadata(lv)) {
|
||||
log_error_once("Online metadata resize for %s/%s is not supported.",
|
||||
lp->vg_name, lp->lv_name);
|
||||
return 0;
|
||||
}
|
||||
lp->poolmetadatasize = (first_seg(lv)->metadata_lv->size *
|
||||
policy_amount + 99) / 100;
|
||||
lp->poolmetadatasign = SIGN_PLUS;
|
||||
}
|
||||
|
||||
if (!lv_thin_pool_percent(lv, 0, &percent))
|
||||
return_0;
|
||||
if (!(PERCENT_0 < percent && percent <= PERCENT_100) ||
|
||||
percent <= policy_threshold)
|
||||
return 1; /* nothing to do */
|
||||
return 1;
|
||||
} else {
|
||||
if (!lv_snapshot_percent(lv, &percent))
|
||||
return_0;
|
||||
@ -326,6 +346,7 @@ static int _adjust_policy_params(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
lp->extents = policy_amount;
|
||||
lp->sizeargs = (lp->extents) ? 1 : 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -358,6 +379,74 @@ static uint32_t lvseg_get_stripes(struct lv_segment *seg, uint32_t *stripesize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lvresize_poolmetadata(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct lvresize_params *lp,
|
||||
const struct logical_volume *pool_lv,
|
||||
struct dm_list *pvh,
|
||||
alloc_policy_t alloc)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *mseg;
|
||||
uint32_t extents;
|
||||
uint32_t seg_mirrors;
|
||||
|
||||
if (!pool_can_resize_metadata(pool_lv)) {
|
||||
log_error("Support for online metadata resize not detected.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lp->poolmetadatasize % vg->extent_size) {
|
||||
lp->poolmetadatasize += vg->extent_size -
|
||||
(lp->poolmetadatasize % vg->extent_size);
|
||||
log_print_unless_silent("Rounding pool metadata size to boundary between physical extents: %s",
|
||||
display_size(cmd, lp->poolmetadatasize));
|
||||
}
|
||||
|
||||
if (!(extents = extents_from_size(vg->cmd, lp->poolmetadatasize,
|
||||
vg->extent_size)))
|
||||
return_0;
|
||||
|
||||
lv = first_seg(pool_lv)->metadata_lv;
|
||||
if (lp->poolmetadatasign == SIGN_PLUS) {
|
||||
if (extents >= (MAX_EXTENT_COUNT - lv->le_count)) {
|
||||
log_error("Unable to extend %s by %u extents, exceeds limit (%u).",
|
||||
lv->name, lv->le_count, MAX_EXTENT_COUNT);
|
||||
return 0;
|
||||
}
|
||||
extents += lv->le_count;
|
||||
}
|
||||
|
||||
if (extents * vg->extent_size > DM_THIN_MAX_METADATA_SIZE) {
|
||||
log_print_unless_silent("Rounding size to maximum supported size 16GiB "
|
||||
"for metadata volume %s.", lv->name);
|
||||
extents = (DM_THIN_MAX_METADATA_SIZE + vg->extent_size - 1) /
|
||||
vg->extent_size;
|
||||
}
|
||||
|
||||
if (extents == lv->le_count) {
|
||||
log_print_unless_silent("Metadata volume %s has already %s.",
|
||||
lv->name, display_size(cmd, lv->size));
|
||||
return 2;
|
||||
}
|
||||
|
||||
log_print_unless_silent("Extending logical volume %s to %s.",
|
||||
lv->name,
|
||||
display_size(cmd, (uint64_t) extents * vg->extent_size));
|
||||
mseg = last_seg(lv);
|
||||
seg_mirrors = lv_mirror_count(lv);
|
||||
if (!lv_extend(lv,
|
||||
mseg->segtype,
|
||||
mseg->area_count / seg_mirrors,
|
||||
mseg->stripe_size,
|
||||
seg_mirrors,
|
||||
mseg->region_size,
|
||||
extents - lv->le_count, NULL,
|
||||
pvh, alloc))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct lvresize_params *lp)
|
||||
{
|
||||
@ -485,6 +574,8 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (lp->sizeargs) { /* TODO: reindent or move to function */
|
||||
|
||||
switch(lp->percent) {
|
||||
case PERCENT_VG:
|
||||
lp->extents = percent_of_extents(lp->extents, vg->extent_count,
|
||||
@ -552,6 +643,11 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
}
|
||||
|
||||
if (lp->extents == lv->le_count) {
|
||||
/* A bit of hack - but still may resize metadata */
|
||||
if (lp->poolmetadatasize) {
|
||||
lp->sizeargs = 0;
|
||||
goto metadata_resize;
|
||||
}
|
||||
if (use_policy)
|
||||
return ECMD_PROCESSED; /* Nothing to do. */
|
||||
if (!lp->resizefs) {
|
||||
@ -778,6 +874,9 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
log_warn("Thin pool volumes do not have filesystem.");
|
||||
lp->resizefs = 0;
|
||||
}
|
||||
} else if (lp->poolmetadatasize) {
|
||||
log_error("--poolmetadatasize can be used only with thin pools.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if ((lp->resize == LV_REDUCE) && lp->argc)
|
||||
@ -832,18 +931,34 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
/* If thin metadata, must suspend thin pool */
|
||||
if (lv_is_thin_pool_metadata(lv)) {
|
||||
if (!(lock_lv = find_pool_lv(lv)))
|
||||
return_0;
|
||||
/* If snapshot, must suspend all associated devices */
|
||||
} else if (lv_is_cow(lv))
|
||||
lock_lv = origin_from_cow(lv);
|
||||
else
|
||||
lock_lv = lv;
|
||||
|
||||
} /* lp->sizeargs */
|
||||
|
||||
if (lp->poolmetadatasize) {
|
||||
metadata_resize:
|
||||
if (!(status = _lvresize_poolmetadata(cmd, vg, lp, lv, pvh, alloc))) {
|
||||
stack;
|
||||
return ECMD_FAILED;
|
||||
} else if ((status == 2) && !lp->sizeargs)
|
||||
return ECMD_PROCESSED;
|
||||
lock_lv = lv;
|
||||
}
|
||||
|
||||
/* store vg on disk(s) */
|
||||
if (!vg_write(vg)) {
|
||||
stack;
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
/* If snapshot, must suspend all associated devices */
|
||||
if (lv_is_cow(lv))
|
||||
lock_lv = origin_from_cow(lv);
|
||||
else
|
||||
lock_lv = lv;
|
||||
|
||||
if (!suspend_lv(cmd, lock_lv)) {
|
||||
log_error("Failed to suspend %s", lock_lv->name);
|
||||
vg_revert(vg);
|
||||
|
Loading…
Reference in New Issue
Block a user