mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-30 10:50:34 +03:00
o Added lvextend
o Full signed arguments to lvreduce/lvextend o Consistent lv_number/pe map use o Populate pv->pe_allocated o Fixes for allocation/writing of multiple LVs
This commit is contained in:
parent
4f0a4a6a7a
commit
7858f6fb16
@ -196,6 +196,7 @@ static int _read_lvs(struct disk_list *data)
|
||||
unsigned long pos;
|
||||
struct lvd_list *ll;
|
||||
|
||||
/* FIXME May be gaps - use lv_max */
|
||||
for(i = 0; i < data->vgd.lv_cur; i++) {
|
||||
pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
|
||||
ll = pool_alloc(data->mem, sizeof(*ll));
|
||||
@ -384,9 +385,9 @@ static int _write_lvs(struct disk_list *data)
|
||||
struct list *lvh;
|
||||
unsigned long pos;
|
||||
|
||||
pos = data->pvd.lv_on_disk.base;
|
||||
list_iterate(lvh, &data->lvds) {
|
||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
||||
pos = data->pvd.lv_on_disk.base;
|
||||
|
||||
if (!_write_lvd(data->dev, pos, &ll->lvd))
|
||||
fail;
|
||||
|
@ -144,9 +144,9 @@ struct lvd_list {
|
||||
};
|
||||
|
||||
struct disk_list {
|
||||
struct list list;
|
||||
struct pool *mem;
|
||||
struct device *dev;
|
||||
struct list list;
|
||||
|
||||
struct pv_disk pvd;
|
||||
struct vg_disk vgd;
|
||||
|
@ -493,6 +493,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
||||
}
|
||||
|
||||
export_lv(&lvdl->lvd, vg, &ll->lv, prefix);
|
||||
lvdl->lvd.lv_number = lv_num;
|
||||
if (!export_extents(dl, lv_num++, &ll->lv, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
@ -556,11 +557,6 @@ void export_numbers(struct list *pvs, struct volume_group *vg)
|
||||
list_iterate(pvh, pvs) {
|
||||
dl = list_item(pvh, struct disk_list);
|
||||
dl->pvd.pv_number = pv_num++;
|
||||
|
||||
list_iterate(lvh, &dl->lvds) {
|
||||
ll = list_item(lvh, struct lvd_list);
|
||||
ll->lvd.lv_number = _get_lv_number(vg, ll->lvd.lv_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,11 +64,11 @@ static int _alloc_contiguous(struct logical_volume *lv,
|
||||
struct pv_map *pvm;
|
||||
struct pv_area *pva, *biggest;
|
||||
|
||||
list_iterate (tmp1, pvms) {
|
||||
list_iterate(tmp1, pvms) {
|
||||
pvm = list_item(tmp1, struct pv_map);
|
||||
biggest = NULL;
|
||||
|
||||
list_iterate (tmp2, &pvm->areas) {
|
||||
list_iterate(tmp2, &pvm->areas) {
|
||||
pva = list_item(tmp2, struct pv_area);
|
||||
|
||||
if (!biggest || (pva->count > biggest->count))
|
||||
@ -85,7 +85,7 @@ static int _alloc_contiguous(struct logical_volume *lv,
|
||||
|
||||
if (allocated != lv->le_count) {
|
||||
log_error("Insufficient free extents to "
|
||||
"allocate logical volume %s: %u required",
|
||||
"allocate logical volume %s: %u required",
|
||||
lv->name, lv->le_count);
|
||||
return 0;
|
||||
}
|
||||
@ -104,10 +104,10 @@ static int _alloc_simple(struct logical_volume *lv,
|
||||
struct pv_map *pvm;
|
||||
struct pv_area *pva;
|
||||
|
||||
list_iterate (tmp1, pvms) {
|
||||
list_iterate(tmp1, pvms) {
|
||||
pvm = list_item(tmp1, struct pv_map);
|
||||
|
||||
list_iterate (tmp2, &pvm->areas) {
|
||||
list_iterate(tmp2, &pvm->areas) {
|
||||
pva = list_item(tmp2, struct pv_area);
|
||||
allocated += _alloc_area(lv, allocated, pvm->pv, pva);
|
||||
|
||||
@ -115,13 +115,13 @@ static int _alloc_simple(struct logical_volume *lv,
|
||||
break;
|
||||
}
|
||||
|
||||
if (allocated == lv->le_count) /* FIXME: yuck, repeated test */
|
||||
if (allocated == lv->le_count) /* FIXME: yuck, repeated test */
|
||||
break;
|
||||
}
|
||||
|
||||
if (allocated != lv->le_count) {
|
||||
log_error("Insufficient free logical extents to "
|
||||
"allocate logical volume %s: %u required",
|
||||
"allocate logical volume %s: %u required",
|
||||
lv->name, lv->le_count);
|
||||
return 0;
|
||||
}
|
||||
@ -162,11 +162,10 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
r = _alloc_simple(lv, pvms, allocated);
|
||||
|
||||
if (r) {
|
||||
vg->lv_count++;
|
||||
vg->free_count -= lv->le_count - allocated;
|
||||
}
|
||||
|
||||
out:
|
||||
out:
|
||||
pool_destroy(scratch);
|
||||
return r;
|
||||
}
|
||||
@ -182,6 +181,7 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
{
|
||||
struct lv_list *ll = NULL;
|
||||
struct logical_volume *lv;
|
||||
int i;
|
||||
|
||||
if (!extents) {
|
||||
log_error("Unable to create logical volume %s with no extents",
|
||||
@ -217,7 +217,6 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
lv->vg = vg;
|
||||
lv->status = status;
|
||||
lv->read_ahead = 0;
|
||||
lv->stripes = stripes;
|
||||
@ -234,18 +233,24 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (i = 0; i < lv->le_count; i++) {
|
||||
lv->map[i].pv->pe_allocated++;
|
||||
}
|
||||
|
||||
vg->lv_count++;
|
||||
list_add(&vg->lvs, &ll->list);
|
||||
lv->vg = vg;
|
||||
|
||||
return lv;
|
||||
|
||||
bad:
|
||||
bad:
|
||||
if (ll)
|
||||
pool_free(ios->mem, ll);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lv_reduce(struct io_space *ios,
|
||||
struct logical_volume *lv, uint32_t extents)
|
||||
int lv_reduce(struct io_space *ios, struct logical_volume *lv, uint32_t extents)
|
||||
{
|
||||
if (extents % lv->stripes) {
|
||||
log_error("For a striped volume you must reduce by a "
|
||||
@ -270,6 +275,7 @@ int lv_extend(struct io_space *ios,
|
||||
{
|
||||
struct pe_specifier *new_map;
|
||||
struct logical_volume *new_lv;
|
||||
int i;
|
||||
|
||||
if (!(new_map = pool_zalloc(ios->mem, sizeof(*new_map) *
|
||||
(extents + lv->le_count)))) {
|
||||
@ -289,18 +295,22 @@ int lv_extend(struct io_space *ios,
|
||||
new_lv->map = new_map;
|
||||
new_lv->le_count += extents;
|
||||
|
||||
if (!_allocate(new_lv->vg, new_lv, acceptable_pvs, new_lv->le_count)) {
|
||||
if (!_allocate(new_lv->vg, new_lv, acceptable_pvs, lv->le_count)) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (i = lv->le_count; i < new_lv->le_count; i++) {
|
||||
new_lv->map[i].pv->pe_allocated++;
|
||||
}
|
||||
|
||||
memcpy(lv, new_lv, sizeof(*lv));
|
||||
|
||||
/* now you see why new_lv had to be allocated last */
|
||||
pool_free(ios->mem, new_lv);
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
bad:
|
||||
pool_free(ios->mem, new_map);
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
struct physical_volume *pv;
|
||||
|
||||
log_verbose("Adding physical volume '%s' to volume group '%s'",
|
||||
pv_name, vg->name);
|
||||
pv_name, vg->name);
|
||||
|
||||
if (!(pvl = pool_alloc(ios->mem, sizeof (*pvl)))) {
|
||||
log_error("pv_list allocation for '%s' failed", pv_name);
|
||||
@ -100,7 +100,7 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
}
|
||||
|
||||
int vg_extend(struct io_space *ios, struct volume_group *vg, int pv_count,
|
||||
char **pv_names)
|
||||
char **pv_names)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -133,14 +133,13 @@ struct volume_group *vg_create(struct io_space *ios, const char *vg_name,
|
||||
}
|
||||
|
||||
if (!id_create(&vg->id)) {
|
||||
log_err("Couldn't create uuid for volume group '%s'.",
|
||||
vg_name);
|
||||
log_err("Couldn't create uuid for volume group '%s'.", vg_name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Strip prefix if present */
|
||||
if (!strncmp(vg_name, ios->prefix, strlen(ios->prefix)))
|
||||
vg_name += strlen(ios->prefix);
|
||||
/* Strip prefix if present */
|
||||
if (!strncmp(vg_name, ios->prefix, strlen(ios->prefix)))
|
||||
vg_name += strlen(ios->prefix);
|
||||
|
||||
if (!(vg->name = pool_strdup(ios->mem, vg_name))) {
|
||||
stack;
|
||||
@ -246,11 +245,11 @@ struct list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||
else
|
||||
ptr = lv_name;
|
||||
|
||||
list_iterate(lvh, &vg->lvs)
|
||||
if (!strcmp(list_item(lvh, struct lv_list)->lv.name, ptr))
|
||||
return lvh;
|
||||
list_iterate(lvh, &vg->lvs)
|
||||
if (!strcmp(list_item(lvh, struct lv_list)->lv.name, ptr))
|
||||
return lvh;
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
|
||||
@ -266,23 +265,30 @@ struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
|
||||
struct physical_volume *_find_pv(struct volume_group *vg, struct device *dev)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pl;
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pl;
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pl = list_item(pvh, struct pv_list);
|
||||
pv = &pl->pv;
|
||||
if (dev == pv->dev)
|
||||
return pv;
|
||||
}
|
||||
return NULL;
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pl = list_item(pvh, struct pv_list);
|
||||
pv = &pl->pv;
|
||||
if (dev == pv->dev)
|
||||
return pv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lv_remove(struct volume_group *vg, struct list *lvh)
|
||||
{
|
||||
int i;
|
||||
struct logical_volume *lv;
|
||||
|
||||
lv = &list_item(lvh, struct lv_list)->lv;
|
||||
for (i = 0; i < lv->le_count; i++) {
|
||||
lv->map[i].pv->pe_allocated--;
|
||||
}
|
||||
|
||||
list_del(lvh);
|
||||
vg->lv_count--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ SOURCES=\
|
||||
lvchange.c \
|
||||
lvcreate.c \
|
||||
lvdisplay.c \
|
||||
lvextend.c \
|
||||
lvm.c \
|
||||
lvmchange.c \
|
||||
lvreduce.c \
|
||||
|
@ -39,11 +39,11 @@ xx(stripes_ARG, 'i', "stripes", int_arg)
|
||||
xx(iop_version_ARG, 'i', "iop_version", NULL)
|
||||
xx(logicalvolume_ARG, 'l', "logicalvolume", int_arg)
|
||||
xx(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg)
|
||||
xx(extents_ARG, 'l', "extents", int_arg)
|
||||
xx(extents_ARG, 'l', "extents", int_arg_with_sign)
|
||||
xx(lvmpartition_ARG, 'l', "lvmpartition", NULL)
|
||||
xx(list_ARG, 'l', "list", NULL)
|
||||
xx(size_ARG, 'L', "size", size_arg)
|
||||
xx(logicalextent_ARG, 'L', "logicalextent", int_arg)
|
||||
xx(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
|
||||
xx(name_ARG, 'n', "name", string_arg)
|
||||
xx(oldpath_ARG, 'n', "oldpath", NULL)
|
||||
xx(nofsck_ARG, 'n', "nofsck", NULL)
|
||||
|
@ -144,9 +144,12 @@ int lvcreate(int argc, char **argv)
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
if (list_item(pvl, struct pv_list)->pv.pe_count ==
|
||||
list_item(pvl, struct pv_list)->pv.pe_allocated)
|
||||
list_item(pvl, struct pv_list)->pv.pe_allocated) {
|
||||
log_error("No free extents on physical volume"
|
||||
" %s", argv[opt]);
|
||||
continue;
|
||||
/* FIXME But check not null at end! */
|
||||
}
|
||||
list_add(pvh, pvl);
|
||||
}
|
||||
} else {
|
||||
|
188
tools/lvextend.c
Normal file
188
tools/lvextend.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
*
|
||||
* LVM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* LVM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LVM; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
int lvextend(int argc, char **argv)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct logical_volume *lv;
|
||||
uint32_t extents = 0;
|
||||
uint32_t size = 0;
|
||||
sign_t sign = SIGN_NONE;
|
||||
char *lv_name, *vg_name;
|
||||
char *st;
|
||||
char *dummy;
|
||||
struct list *lvh, *pvh, *pvl;
|
||||
int opt = 0;
|
||||
|
||||
if (arg_count(extents_ARG) + arg_count(size_ARG) != 1) {
|
||||
log_error("Please specify either size or extents (not both)");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (arg_count(extents_ARG)) {
|
||||
extents = arg_int_value(extents_ARG, 0);
|
||||
sign = arg_sign_value(extents_ARG, SIGN_NONE);
|
||||
}
|
||||
|
||||
if (arg_count(size_ARG)) {
|
||||
size = arg_int_value(size_ARG, 0);
|
||||
sign = arg_sign_value(extents_ARG, SIGN_NONE);
|
||||
}
|
||||
|
||||
if (sign == SIGN_MINUS) {
|
||||
log_error("Negative argument not permitted - use lvreduce");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please provide the logical volume name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
lv_name = argv[0];
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
if (!(vg_name = extract_vgname(ios, lv_name))) {
|
||||
log_error("Please provide a volume group name");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if ((st = strrchr(lv_name, '/')))
|
||||
lv_name = st + 1;
|
||||
|
||||
/* does VG exist? */
|
||||
log_verbose("Finding volume group %s", vg_name);
|
||||
if (!(vg = ios->vg_read(ios, vg_name))) {
|
||||
log_error("Volume group %s doesn't exist", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vg->status & ACTIVE)) {
|
||||
log_error("Volume group %s must be active before changing a "
|
||||
"logical volume", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
/* does LV exist? */
|
||||
if (!(lvh = find_lv_in_vg(vg, lv_name))) {
|
||||
log_error("Logical volume %s not found in volume group %s",
|
||||
lv_name, vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
lv = &list_item(lvh, struct lv_list)->lv;
|
||||
|
||||
if (!(lv->status & ACTIVE)) {
|
||||
log_error("Logical volume %s must be active before change",
|
||||
lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
/* Build up list of PVs */
|
||||
if (!(pvh = pool_alloc(ios->mem, sizeof (struct list)))) {
|
||||
log_error("pvh list allocation failed");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
list_init(pvh);
|
||||
for (; opt < argc; opt++) {
|
||||
if (!(pvl = find_pv_in_vg(vg, argv[opt]))) {
|
||||
log_error("Physical Volume %s not found in "
|
||||
"Volume Group %s", argv[opt],
|
||||
vg->name);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
if (list_item(pvl, struct pv_list)->pv.pe_count ==
|
||||
list_item(pvl, struct pv_list)->pv.pe_allocated) {
|
||||
log_error("No free extents on physical volume"
|
||||
" %s", argv[opt]);
|
||||
continue;
|
||||
/* FIXME Buy check not empty at end! */
|
||||
}
|
||||
list_add(pvh, pvl);
|
||||
}
|
||||
} else {
|
||||
/* Use full list from VG */
|
||||
pvh = &vg->pvs;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
/* No of 512-byte sectors */
|
||||
extents = size * 2;
|
||||
|
||||
if (extents % vg->extent_size) {
|
||||
char *s1;
|
||||
|
||||
extents += vg->extent_size -
|
||||
(extents % vg->extent_size);
|
||||
log_print("Rounding up size to full physical extent %s",
|
||||
(s1 = display_size(extents / 2, SIZE_SHORT)));
|
||||
dbg_free(s1);
|
||||
}
|
||||
|
||||
extents /= vg->extent_size;
|
||||
}
|
||||
|
||||
if (sign == SIGN_PLUS)
|
||||
extents += lv->le_count;
|
||||
|
||||
if (extents <= lv->le_count) {
|
||||
log_error("New size given (%d extents) not larger than "
|
||||
"existing size (%d extents)", extents, lv->le_count);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (!extents) {
|
||||
log_error("New size of 0 not permitted");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
log_print("Extending logical volume %s to %s", lv_name,
|
||||
(dummy =
|
||||
display_size(extents * vg->extent_size / 2, SIZE_SHORT)));
|
||||
dbg_free(dummy);
|
||||
|
||||
lv_extend(ios, lv, extents - lv->le_count, pvh);
|
||||
/* where parm is always *increase* not actual */
|
||||
|
||||
/********* FIXME Suspend lv ***********/
|
||||
|
||||
/* store vg on disk(s) */
|
||||
if (!ios->vg_write(ios, vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* FIXME Ensure it always displays errors? */
|
||||
if (!lv_reactivate(lv))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/********* FIXME Resume *********/
|
||||
|
||||
/********* FIXME Backup
|
||||
if ((ret = do_autobackup(vg_name, vg)))
|
||||
return ret;
|
||||
************/
|
||||
|
||||
log_print("Logical volume %s successfully extended", lv_name);
|
||||
|
||||
return 0;
|
||||
}
|
92
tools/lvm.c
92
tools/lvm.c
@ -157,6 +157,8 @@ void usage(const char *name)
|
||||
|
||||
int yes_no_arg(struct arg *a)
|
||||
{
|
||||
a->sign = SIGN_NONE;
|
||||
|
||||
if (!strcmp(a->value, "y"))
|
||||
a->i_value = 1;
|
||||
|
||||
@ -169,15 +171,44 @@ int yes_no_arg(struct arg *a)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _get_int_arg(struct arg *a, char **ptr)
|
||||
{
|
||||
char *val;
|
||||
long v;
|
||||
|
||||
val = a->value;
|
||||
switch (*val) {
|
||||
case '+':
|
||||
a->sign = SIGN_PLUS;
|
||||
val++;
|
||||
break;
|
||||
case '-':
|
||||
a->sign = SIGN_MINUS;
|
||||
val++;
|
||||
break;
|
||||
default:
|
||||
a->sign = SIGN_NONE;
|
||||
}
|
||||
|
||||
if (!isdigit(*val))
|
||||
return 0;
|
||||
|
||||
v = strtol(val, ptr, 10);
|
||||
|
||||
if (*ptr == val)
|
||||
return 0;
|
||||
|
||||
a->i_value = (uint32_t) v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int size_arg(struct arg *a)
|
||||
{
|
||||
static char *suffixes = "kmgt";
|
||||
|
||||
char *ptr;
|
||||
int i;
|
||||
long v = strtol(a->value, &ptr, 10);
|
||||
static char *suffixes = "kmgt";
|
||||
|
||||
if (ptr == a->value)
|
||||
if (!_get_int_arg(a, &ptr))
|
||||
return 0;
|
||||
|
||||
if (*ptr) {
|
||||
@ -189,10 +220,9 @@ int size_arg(struct arg *a)
|
||||
return 0;
|
||||
|
||||
while (i-- > 0)
|
||||
v *= 1024;
|
||||
a->i_value *= 1024;
|
||||
}
|
||||
|
||||
a->i_value = (int) v;
|
||||
return 1;
|
||||
|
||||
}
|
||||
@ -200,12 +230,20 @@ int size_arg(struct arg *a)
|
||||
int int_arg(struct arg *a)
|
||||
{
|
||||
char *ptr;
|
||||
long v = strtol(a->value, &ptr, 10);
|
||||
|
||||
if (ptr == a->value || *ptr)
|
||||
if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int int_arg_with_sign(struct arg *a)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if (!_get_int_arg(a, &ptr) || (*ptr))
|
||||
return 0;
|
||||
|
||||
a->i_value = (int) v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -216,6 +254,8 @@ int string_arg(struct arg *a)
|
||||
|
||||
int permission_arg(struct arg *a)
|
||||
{
|
||||
a->sign = SIGN_NONE;
|
||||
|
||||
if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr")))
|
||||
a->i_value = LVM_READ | LVM_WRITE;
|
||||
|
||||
@ -242,8 +282,7 @@ char yes_no_prompt(const char *prompt, ...)
|
||||
c = tolower(getchar());
|
||||
}
|
||||
|
||||
while (getchar() != '\n')
|
||||
;
|
||||
while (getchar() != '\n') ;
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -271,7 +310,7 @@ static void register_command(const char *name, command_fn fn,
|
||||
va_end(ap);
|
||||
|
||||
/* allocate space for them */
|
||||
if (!(args = dbg_malloc(sizeof (*args) * nargs))) {
|
||||
if (!(args = dbg_malloc(sizeof(*args) * nargs))) {
|
||||
log_fatal("Out of memory.");
|
||||
exit(ECMD_FAILED);
|
||||
}
|
||||
@ -327,7 +366,7 @@ static void create_new_command(const char *name, command_fn command,
|
||||
|
||||
static void __alloc(int size)
|
||||
{
|
||||
if (!(_commands = dbg_realloc(_commands, sizeof (*_commands) * size))) {
|
||||
if (!(_commands = dbg_realloc(_commands, sizeof(*_commands) * size))) {
|
||||
log_fatal("Couldn't allocate memory.");
|
||||
exit(ECMD_FAILED);
|
||||
}
|
||||
@ -385,7 +424,7 @@ static int process_command_line(struct command *com, int *argc, char ***argv)
|
||||
add_getopt_arg(com->valid_args[i], &ptr, &o);
|
||||
|
||||
*ptr = '\0';
|
||||
memset(o, 0, sizeof (*o));
|
||||
memset(o, 0, sizeof(*o));
|
||||
|
||||
/* initialise getopt_long & scan for command line switches */
|
||||
optarg = 0;
|
||||
@ -609,7 +648,8 @@ static int dev_cache_setup(void)
|
||||
"device cache");
|
||||
return 0;
|
||||
}
|
||||
log_verbose("device/scan not in config file: Defaulting to /dev");
|
||||
log_verbose
|
||||
("device/scan not in config file: Defaulting to /dev");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -619,14 +659,14 @@ static int dev_cache_setup(void)
|
||||
"devices/scan");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (!dev_cache_add_dir(cv->v.str)) {
|
||||
log_error("Failed to add %s to internal device cache",
|
||||
log_error("Failed to add %s to internal device cache",
|
||||
cv->v.str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -669,7 +709,7 @@ static struct dev_filter *filter_setup(void)
|
||||
return 0;
|
||||
|
||||
lvm_cache = find_config_str(_cf->root, "devices/cache", '/',
|
||||
"/etc/lvm/.cache");
|
||||
"/etc/lvm/.cache");
|
||||
|
||||
if (!(f4 = persistent_filter_create(f3, lvm_cache))) {
|
||||
log_error("Failed to create persistent device filter");
|
||||
@ -679,7 +719,7 @@ static struct dev_filter *filter_setup(void)
|
||||
/* Should we ever dump persistent filter state? */
|
||||
if (find_config_int(_cf->root, "devices/write_cache_state", '/', 1))
|
||||
dump_filter = 1;
|
||||
|
||||
|
||||
if (!stat(lvm_cache, &st) && !persistent_filter_load(f4))
|
||||
log_verbose("Failed to load existing device cache from %s",
|
||||
lvm_cache);
|
||||
@ -694,7 +734,7 @@ static int init(void)
|
||||
struct stat info;
|
||||
struct pool *ios_pool;
|
||||
|
||||
/* FIXME: Override from config file. (Append trailing slash if reqd)*/
|
||||
/* FIXME: Override from config file. (Append trailing slash if reqd) */
|
||||
char *prefix = "/dev/";
|
||||
|
||||
if (!(_cf = create_config_file())) {
|
||||
@ -781,15 +821,15 @@ static int run_script(int argc, char **argv)
|
||||
if ((script = fopen(argv[0], "r")) == NULL)
|
||||
return ENO_SUCH_CMD;
|
||||
|
||||
while (fgets(buffer, sizeof (buffer), script) != NULL) {
|
||||
while (fgets(buffer, sizeof(buffer), script) != NULL) {
|
||||
if (!magic_number) {
|
||||
if (buffer[0] == '#' && buffer[1] == '!')
|
||||
magic_number = 1;
|
||||
else
|
||||
return ENO_SUCH_CMD;
|
||||
}
|
||||
if ((strlen(buffer) == sizeof (buffer) - 1)
|
||||
&& (buffer[sizeof (buffer) - 1] - 2 != '\n')) {
|
||||
if ((strlen(buffer) == sizeof(buffer) - 1)
|
||||
&& (buffer[sizeof(buffer) - 1] - 2 != '\n')) {
|
||||
buffer[50] = '\0';
|
||||
log_error("Line too long (max 255) beginning: %s",
|
||||
buffer);
|
||||
@ -901,7 +941,7 @@ static char *list_args(char *text, int state)
|
||||
char c;
|
||||
if (!(c = (the_args +
|
||||
com->valid_args[match_no++])->short_arg))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
sprintf(s, "-%c", c);
|
||||
if (!strncmp(text, s, len))
|
||||
|
@ -25,22 +25,32 @@ int lvreduce(int argc, char **argv)
|
||||
struct volume_group *vg;
|
||||
struct logical_volume *lv;
|
||||
struct list *lvh;
|
||||
int32_t extents = 0;
|
||||
int32_t size = 0;
|
||||
uint32_t extents = 0;
|
||||
uint32_t size = 0;
|
||||
sign_t sign = SIGN_NONE;
|
||||
char *lv_name, *vg_name;
|
||||
char *st;
|
||||
int i;
|
||||
|
||||
if (arg_count(extents_ARG) + arg_count(size_ARG) != 1) {
|
||||
log_error("Please specify either size or extents (not both)");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
/* FIXME signed use throughout halves the maximum... */
|
||||
if (arg_count(extents_ARG))
|
||||
if (arg_count(extents_ARG)) {
|
||||
extents = arg_int_value(extents_ARG, 0);
|
||||
sign = arg_sign_value(extents_ARG, SIGN_NONE);
|
||||
}
|
||||
|
||||
if (arg_count(size_ARG))
|
||||
if (arg_count(size_ARG)) {
|
||||
size = arg_int_value(size_ARG, 0);
|
||||
sign = arg_sign_value(extents_ARG, SIGN_NONE);
|
||||
}
|
||||
|
||||
if (sign == SIGN_PLUS) {
|
||||
log_error("Positive sign not permitted - use lvextend");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (!argc) {
|
||||
log_error("Please provide the logical volume name");
|
||||
@ -94,15 +104,18 @@ int lvreduce(int argc, char **argv)
|
||||
if (extents % vg->extent_size) {
|
||||
char *s1;
|
||||
|
||||
extents += (signed) vg->extent_size -
|
||||
(signed) (extents % vg->extent_size);
|
||||
if (sign == SIGN_NONE)
|
||||
extents += vg->extent_size -
|
||||
(extents % vg->extent_size);
|
||||
else
|
||||
extents -= extents % vg->extent_size;
|
||||
|
||||
log_print("Rounding up size to full physical extent %s",
|
||||
(s1 =
|
||||
display_size(abs(extents) / 2, SIZE_SHORT)));
|
||||
(s1 = display_size(extents / 2, SIZE_SHORT)));
|
||||
dbg_free(s1);
|
||||
}
|
||||
|
||||
extents /= (signed) vg->extent_size;
|
||||
extents /= vg->extent_size;
|
||||
}
|
||||
|
||||
if (!extents) {
|
||||
@ -110,14 +123,14 @@ int lvreduce(int argc, char **argv)
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (extents < 0) {
|
||||
if (1 - extents > lv->le_count) {
|
||||
if (sign == SIGN_MINUS) {
|
||||
if (extents >= lv->le_count) {
|
||||
log_error("Unable to reduce %s below 1 extent",
|
||||
lv_name);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
lv->le_count += extents;
|
||||
extents = lv->le_count - extents;
|
||||
} else {
|
||||
if (extents >= lv->le_count) {
|
||||
log_error("New size given (%d extents) not less than "
|
||||
@ -125,7 +138,6 @@ int lvreduce(int argc, char **argv)
|
||||
lv->le_count);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
lv->le_count = extents;
|
||||
}
|
||||
|
||||
/************ FIXME Stripes
|
||||
@ -144,7 +156,7 @@ int lvreduce(int argc, char **argv)
|
||||
log_print("WARNING: Reducing active%s logical volume to %s",
|
||||
(lv_open_count(lv) > 0) ? " and open" : "",
|
||||
(dummy =
|
||||
display_size(lv->le_count * vg->extent_size / 2,
|
||||
display_size(extents * vg->extent_size / 2,
|
||||
SIZE_SHORT)));
|
||||
log_print("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
|
||||
dbg_free(dummy);
|
||||
@ -159,6 +171,12 @@ int lvreduce(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = extents; i < lv->le_count; i++) {
|
||||
lv->map[i].pv->pe_allocated--;
|
||||
}
|
||||
|
||||
lv->le_count = extents;
|
||||
|
||||
/********* FIXME Suspend lv ***********/
|
||||
|
||||
/* store vg on disk(s) */
|
||||
@ -180,4 +198,3 @@ int lvreduce(int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -121,4 +121,3 @@ int lvremove_single(char *lv_name)
|
||||
log_print("logical volume %s successfully removed", lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
*/
|
||||
|
||||
int e2fsadm(int argc, char **argv) {return 1;}
|
||||
int lvextend(int argc, char **argv) {return 1;}
|
||||
int lvmdiskscan(int argc, char **argv) {return 1;}
|
||||
int lvmsadc(int argc, char **argv) {return 1;}
|
||||
int lvmsar(int argc, char **argv) {return 1;}
|
||||
|
@ -62,6 +62,12 @@ enum {
|
||||
#undef xx
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SIGN_NONE = 0,
|
||||
SIGN_PLUS = 1,
|
||||
SIGN_MINUS = 2
|
||||
} sign_t;
|
||||
|
||||
/* a global table of possible arguments */
|
||||
struct arg {
|
||||
char short_arg;
|
||||
@ -69,7 +75,8 @@ struct arg {
|
||||
int (*fn)(struct arg *a);
|
||||
int count;
|
||||
char *value;
|
||||
int i_value;
|
||||
uint32_t i_value;
|
||||
sign_t sign;
|
||||
};
|
||||
|
||||
extern struct arg the_args[ARG_COUNT + 1];
|
||||
@ -80,6 +87,7 @@ void usage(const char *name);
|
||||
int yes_no_arg(struct arg *a);
|
||||
int size_arg(struct arg *a);
|
||||
int int_arg(struct arg *a);
|
||||
int int_arg_with_sign(struct arg *a);
|
||||
int string_arg(struct arg *a);
|
||||
int permission_arg(struct arg *a);
|
||||
|
||||
@ -99,11 +107,16 @@ static inline char *arg_str_value(int a, char *def)
|
||||
return arg_count(a) ? the_args[a].value : def;
|
||||
}
|
||||
|
||||
static inline int arg_int_value(int a, int def)
|
||||
static inline uint32_t arg_int_value(int a, uint32_t def)
|
||||
{
|
||||
return arg_count(a) ? the_args[a].i_value : def;
|
||||
}
|
||||
|
||||
static inline sign_t arg_sign_value(int a, sign_t def)
|
||||
{
|
||||
return arg_count(a) ? the_args[a].sign : def;
|
||||
}
|
||||
|
||||
static inline int arg_count_increment(int a)
|
||||
{
|
||||
return the_args[a].count++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user