1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

vgchange --physicalextentsize (but only if it's an exact fit - may need to

use pvmove first)
This commit is contained in:
Alasdair Kergon 2005-04-18 14:56:42 +00:00
parent f1379332dc
commit 66278a80b1
5 changed files with 220 additions and 5 deletions

View File

@ -1,5 +1,6 @@
Version 2.01.10 -
================================
vgchange --physicalextentsize
Internal snapshot restructuring.
Remove unused internal non-persistent snapshot option.
Allow offline extension of snapshot volumes.

View File

@ -281,6 +281,153 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
return NULL;
}
static int _recalc_extents(uint32_t *extents, const char *desc1,
const char *desc2, uint32_t old_size,
uint32_t new_size)
{
uint64_t size = (uint64_t) old_size * (*extents);
if (size % new_size) {
log_error("New size %" PRIu64 " for %s%s not an exact number "
"of new extents.", size, desc1, desc2);
return 0;
}
size /= new_size;
if (size > UINT32_MAX) {
log_error("New extent count %" PRIu64 " for %s%s exceeds "
"32 bits.", size, desc1, desc2);
return 0;
}
*extents = (uint32_t) size;
return 1;
}
int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
uint32_t new_size)
{
uint32_t old_size = vg->extent_size;
struct pv_list *pvl;
struct lv_list *lvl;
struct physical_volume *pv;
struct logical_volume *lv;
struct lv_segment *seg;
uint32_t s;
vg->extent_size = new_size;
if (vg->fid->fmt->ops->vg_setup &&
!vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
stack;
return 0;
}
if (!_recalc_extents(&vg->extent_count, vg->name, "", old_size,
new_size)) {
stack;
return 0;
}
if (!_recalc_extents(&vg->free_count, vg->name, " free space",
old_size, new_size)) {
stack;
return 0;
}
/* foreach PV */
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
pv->pe_size = new_size;
if (!_recalc_extents(&pv->pe_count, dev_name(pv->dev), "",
old_size, new_size)) {
stack;
return 0;
}
if (!_recalc_extents(&pv->pe_alloc_count, dev_name(pv->dev),
" allocated space", old_size, new_size)) {
stack;
return 0;
}
}
/* foreach LV */
list_iterate_items(lvl, &vg->lvs) {
lv = lvl->lv;
if (!_recalc_extents(&lv->le_count, lv->name, "", old_size,
new_size)) {
stack;
return 0;
}
list_iterate_items(seg, &lv->segments) {
if (!_recalc_extents(&seg->le, lv->name,
" segment start", old_size,
new_size)) {
stack;
return 0;
}
if (!_recalc_extents(&seg->len, lv->name,
" segment length", old_size,
new_size)) {
stack;
return 0;
}
if (!_recalc_extents(&seg->area_len, lv->name,
" area length", old_size,
new_size)) {
stack;
return 0;
}
if (!_recalc_extents(&seg->extents_copied, lv->name,
" extents moved", old_size,
new_size)) {
stack;
return 0;
}
/* foreach area */
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
case AREA_PV:
if (!_recalc_extents
(&seg->area[s].u.pv.pe, lv->name,
" area start", old_size,
new_size)) {
stack;
return 0;
}
break;
case AREA_LV:
if (!_recalc_extents
(&seg->area[s].u.lv.le, lv->name,
" area start", old_size,
new_size)) {
stack;
return 0;
}
break;
default:
log_error("Unrecognised segment type "
"%u", seg->area[s].type);
return 0;
}
}
}
}
return 1;
}
/* Sizes in sectors */
struct physical_volume *pv_create(const struct format_type *fmt,
struct device *dev,

View File

@ -402,6 +402,8 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name);
int vg_extend(struct format_instance *fi, struct volume_group *vg,
int pv_count, char **pv_names);
int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
uint32_t new_extent_size);
/* Manipulate LVs */
struct logical_volume *lv_create_empty(struct format_instance *fi,

View File

@ -569,13 +569,15 @@ xx(vgchange,
"\t -c|--clustered {y|n} |" "\n"
"\t -x|--resizeable {y|n} |" "\n"
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
"\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtT] |" "\n"
"\t --addtag Tag |\n"
"\t --deltag Tag}\n"
"\t[VolumeGroupName...]\n",
addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG,
partial_ARG, resizeable_ARG, resizable_ARG, test_ARG, uuid_ARG)
partial_ARG, physicalextentsize_ARG, resizeable_ARG, resizable_ARG,
test_ARG, uuid_ARG)
xx(vgck,
"Check the consistency of volume group(s)",

View File

@ -251,6 +251,64 @@ static int _vgchange_logicalvolume(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _vgchange_pesize(struct cmd_context *cmd, struct volume_group *vg)
{
uint32_t extent_size;
if (!(vg->status & RESIZEABLE_VG)) {
log_error("Volume group \"%s\" must be resizeable "
"to change PE size", vg->name);
return ECMD_FAILED;
}
if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
log_error("Physical extent size may not be negative");
return EINVALID_CMD_LINE;
}
extent_size = arg_uint_value(cmd, physicalextentsize_ARG, 0) * 2;
if (!extent_size) {
log_error("Physical extent size may not be zero");
return EINVALID_CMD_LINE;
}
if (extent_size == vg->extent_size) {
log_error("Physical extent size of VG %s is already %s",
vg->name, display_size(cmd, extent_size, SIZE_SHORT));
return ECMD_PROCESSED;
}
if (extent_size & (extent_size - 1)) {
log_error("Physical extent size must be a power of 2.");
return EINVALID_CMD_LINE;
}
if (extent_size > vg->extent_size) {
if ((uint64_t) vg->extent_size * vg->extent_count % extent_size) {
/* FIXME Adjust used PV sizes instead */
log_error("New extent size is not a perfect fit");
return EINVALID_CMD_LINE;
}
}
if (!archive(vg))
return ECMD_FAILED;
if (!vg_change_pesize(cmd, vg, extent_size)) {
stack;
return ECMD_FAILED;
}
if (!vg_write(vg) || !vg_commit(vg))
return ECMD_FAILED;
backup(vg);
log_print("Volume group \"%s\" successfully changed", vg->name);
return ECMD_PROCESSED;
}
static int _vgchange_tag(struct cmd_context *cmd, struct volume_group *vg,
int arg)
{
@ -369,6 +427,9 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
else if (arg_count(cmd, deltag_ARG))
r = _vgchange_tag(cmd, vg, deltag_ARG);
else if (arg_count(cmd, physicalextentsize_ARG))
r = _vgchange_pesize(cmd, vg);
else if (arg_count(cmd, uuid_ARG))
r = _vgchange_uuid(cmd, vg);
@ -387,9 +448,10 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
(arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
arg_count(cmd, physicalextentsize_ARG) +
arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG))) {
log_error("One of -a, -c, -l, -x, --alloc, --addtag, --deltag "
"or --uuid required");
log_error("One of -a, -c, -l, -s, -x, --uuid, --alloc, --addtag or "
"--deltag required");
return EINVALID_CMD_LINE;
}
@ -397,8 +459,9 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) > 1) {
log_error("Only one of -a, -c, -l, -x, --uuid, --alloc, "
arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) +
arg_count(cmd, physicalextentsize_ARG) > 1) {
log_error("Only one of -a, -c, -l, -s, -x, --uuid, --alloc, "
"--addtag or --deltag allowed");
return EINVALID_CMD_LINE;
}