summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlasdair Kergon <agk@redhat.com>2001-11-09 22:01:04 +0000
committerAlasdair Kergon <agk@redhat.com>2001-11-09 22:01:04 +0000
commit7858f6fb16b9b2373efa92103e81b46fce897799 (patch)
tree12cc418aac3ba47a42528418eee9f5079086d7c6
parent4f0a4a6a7a13e3c24360a54813208397fbb6c218 (diff)
downloadlvm2-7858f6fb16b9b2373efa92103e81b46fce897799.tar.gz
lvm2-7858f6fb16b9b2373efa92103e81b46fce897799.tar.xz
lvm2-7858f6fb16b9b2373efa92103e81b46fce897799.zip
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
-rw-r--r--lib/format1/disk-rep.c3
-rw-r--r--lib/format1/disk-rep.h2
-rw-r--r--lib/format1/import-export.c6
-rw-r--r--lib/metadata/lv_manip.c40
-rw-r--r--lib/metadata/metadata.c50
-rw-r--r--tools/Makefile.in1
-rw-r--r--tools/args.h4
-rw-r--r--tools/lvcreate.c5
-rw-r--r--tools/lvextend.c188
-rw-r--r--tools/lvm.c92
-rw-r--r--tools/lvreduce.c49
-rw-r--r--tools/lvremove.c1
-rw-r--r--tools/stub.h1
-rw-r--r--tools/tools.h17
14 files changed, 366 insertions, 93 deletions
diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c
index 5ff957a4..af9ead96 100644
--- a/lib/format1/disk-rep.c
+++ b/lib/format1/disk-rep.c
@@ -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;
diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h
index a7f3041d..20b1678e 100644
--- a/lib/format1/disk-rep.h
+++ b/lib/format1/disk-rep.h
@@ -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;
diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c
index 0d016866..23c3d765 100644
--- a/lib/format1/import-export.c
+++ b/lib/format1/import-export.c
@@ -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);
- }
}
}
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index c03af7c7..c4070ae8 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -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;
}
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 8161fabd..24a8eacd 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -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;
-
- list_iterate(pvh, &vg->pvs) {
- pl = list_item(pvh, struct pv_list);
- pv = &pl->pv;
- if (dev == pv->dev)
- return pv;
- }
- return NULL;
+ 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;
}
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;
}
-
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 11db65b5..33505854 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -24,6 +24,7 @@ SOURCES=\
lvchange.c \
lvcreate.c \
lvdisplay.c \
+ lvextend.c \
lvm.c \
lvmchange.c \
lvreduce.c \
diff --git a/tools/args.h b/tools/args.h
index b3a58d06..74f96ea9 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -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)
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 6004ea12..d93faaaf 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -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 {
diff --git a/tools/lvextend.c b/tools/lvextend.c
new file mode 100644
index 00000000..090d55ff
--- /dev/null
+++ b/tools/lvextend.c
@@ -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;
+}
diff --git a/tools/lvm.c b/tools/lvm.c
index f8e9ca89..90da2f4f 100644
--- a/tools/lvm.c
+++ b/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 size_arg(struct arg *a)
+int _get_int_arg(struct arg *a, char **ptr)
{
- static char *suffixes = "kmgt";
+ 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)
+{
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))
diff --git a/tools/lvreduce.c b/tools/lvreduce.c
index e9163e5b..48aaf3f2 100644
--- a/tools/lvreduce.c
+++ b/tools/lvreduce.c
@@ -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;
}
-
diff --git a/tools/lvremove.c b/tools/lvremove.c
index cc2d17f3..20caaa2d 100644
--- a/tools/lvremove.c
+++ b/tools/lvremove.c
@@ -121,4 +121,3 @@ int lvremove_single(char *lv_name)
log_print("logical volume %s successfully removed", lv_name);
return 0;
}
-
diff --git a/tools/stub.h b/tools/stub.h
index a8cfc955..d60eaa74 100644
--- a/tools/stub.h
+++ b/tools/stub.h
@@ -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;}
diff --git a/tools/tools.h b/tools/tools.h
index 767100d7..9ac189f5 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -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++;