summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/activate/activate.c52
-rw-r--r--lib/activate/activate.h4
-rw-r--r--lib/display/display.c293
-rw-r--r--lib/log/log.h2
-rw-r--r--tools/Makefile.in2
-rw-r--r--tools/lvdisplay.c86
-rw-r--r--tools/lvreduce.c183
-rw-r--r--tools/stub.h2
8 files changed, 466 insertions, 158 deletions
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index d34b1cb4..5bc1fa77 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -52,45 +52,41 @@ static struct dm_task *_info(struct logical_volume *lv)
return NULL;
}
-int lv_active(struct logical_volume *lv, int *result)
+int lv_active(struct logical_volume *lv)
{
- int r = 0;
+ int r = -1;
struct dm_task *dmt;
if (!(dmt = _info(lv))) {
stack;
- return 0;
+ return r;
}
- if (!dm_task_exists(dmt, result)) {
+ if (!dm_task_exists(dmt, &r)) {
stack;
goto out;
}
- r = 1;
-
out:
dm_task_destroy(dmt);
return r;
}
-int lv_open_count(struct logical_volume *lv, int *result)
+int lv_open_count(struct logical_volume *lv)
{
- int r = 0;
+ int r = -1;
struct dm_task *dmt;
if (!(dmt = _info(lv))) {
stack;
- return 0;
+ return r;
}
- if (!dm_task_open_count(dmt, result)) {
+ if (!dm_task_open_count(dmt, &r)) {
stack;
goto out;
}
- r = 1;
-
out:
dm_task_destroy(dmt);
return r;
@@ -230,15 +226,12 @@ int activate_lvs_in_vg(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
- int count = 0, exists;
+ int count = 0;
list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
- if (!lv_active(lv, &exists) || exists)
- continue;
-
- count += lv_activate(lv);
+ count += (!lv_active(lv) && lv_activate(lv));
}
return count;
@@ -253,15 +246,12 @@ int deactivate_lvs_in_vg(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
- int count = 0, exists;
+ int count = 0;
list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
- if (!lv_active(lv, &exists) || !exists)
- continue;
-
- count += lv_activate(lv);
+ count += ((lv_active(lv) == 1) && lv_deactivate(lv));
}
return count;
@@ -271,17 +261,12 @@ int lvs_in_vg_activated(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
- int exists, count = 0;
+ int count = 0;
list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
- if (!lv_active(lv, &exists)) {
- stack;
- continue; /* FIXME: what is the right thing here ? */
- }
-
- count += exists ? 1 : 0;
+ count += (lv_active(lv) == 1);
}
return count;
@@ -291,17 +276,12 @@ int lvs_in_vg_opened(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
- int open, count = 0;
+ int count = 0;
list_iterate(lvh, &vg->lvs) {
lv = &(list_item(lvh, struct lv_list)->lv);
- if (!lv_open_count(lv, &open)) {
- stack;
- continue; /* FIXME: what is the right thing here ? */
- }
-
- count += open ? 1 : 0;
+ count += (lv_open_count(lv) == 1);
}
return count;
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index 5c03424c..f033488e 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -9,8 +9,8 @@
/* FIXME Snapshot handling? */
-int lv_active(struct logical_volume *lv, int *result);
-int lv_open_count(struct logical_volume *lv, int *result);
+int lv_active(struct logical_volume *lv);
+int lv_open_count(struct logical_volume *lv);
int lv_activate(struct logical_volume *lv);
int lv_reactivate(struct logical_volume *lv);
diff --git a/lib/display/display.c b/lib/display/display.c
index 4ae15a57..3aca44ff 100644
--- a/lib/display/display.c
+++ b/lib/display/display.c
@@ -24,6 +24,7 @@
#include "dbg_malloc.h"
#include "log.h"
#include "display.h"
+#include "activate.h"
#define SIZE_BUF 128
@@ -205,141 +206,199 @@ void pv_display_short(struct physical_volume *pv)
return;
}
-#if 0
-/******** FIXME
-void pv_display_pe(pv_t * pv, pe_disk_t * pe)
+void lvdisplay_colons(struct logical_volume *lv)
{
- int p;
-
- for (p = 0; p < pv->pe_total; p++)
- printf("pe#: %4d vg: %s lv: %d le: %d\n",
- p, pv->vg_name, pe[p].lv_num, pe[p].le_num);
+ log_print("%s/%s:%s:%d:%d:-1:%d:%llu:%d:-1:%d:%d:-1:-1",
+ /* FIXME Prefix - attach to struct volume_group? */
+ lv->vg->name,
+ lv->name,
+ lv->vg->name,
+ (lv->status & (LVM_READ | LVM_WRITE)) >> 8,
+ lv->status & ACTIVE,
+ /* FIXME lv->lv_number, */
+ lvs_in_vg_opened(lv->vg),
+ lv->size,
+ lv->le_count,
+ /* FIXME num allocated? */
+ (lv->status & (ALLOC_STRICT | ALLOC_CONTIGUOUS)) >> 12,
+ lv->read_ahead
+ /* FIXME device num MAJOR(lv->lv_dev), MINOR(lv->lv_dev) */
+ );
+ return;
+}
+void lvdisplay_extents(struct logical_volume *lv)
+{
return;
}
-*******/
-void pv_display_pe_text(pv_t * pv, pe_disk_t * pe, lv_disk_t * lvs)
+void lvdisplay_full(struct logical_volume *lv)
{
- int flag = 0;
- int lv_num_last = 0;
- int p = 0;
- int pe_free = 0;
- int *pe_this_count = NULL;
- int pt = 0;
- int pt_count = 0;
- lv_disk_t *lv;
- char *lv_name_this = NULL;
- char *lv_names = NULL;
- char *lv_names_sav = NULL;
- pe_disk_t *pe_this = NULL;
-
- if ((pe_this = dbg_malloc(pv->pe_total * sizeof (pe_disk_t))) == NULL) {
- log_error("pe_this allocation failed");
- goto pv_display_pe_text_out;
- }
+ char *size;
+ uint32_t alloc;
- if ((pe_this_count = dbg_malloc(pv->pe_total * sizeof (int))) == NULL) {
- log_error("pe_this_count allocation failed");
- goto pv_display_pe_text_out;
- }
+ log_print("--- Logical volume ---");
- memset(pe_this, 0, pv->pe_total * sizeof (pe_disk_t));
- memset(pe_this_count, 0, pv->pe_total * sizeof (int));
-
- /* get PE and LE summaries */
- pt_count = 0;
- for (p = pt_count; p < pv->pe_total; p++) {
- if (pe[p].lv_num != 0) {
- flag = 0;
- for (pt = 0; pt < pt_count; pt++) {
- if (pe_this[pt].lv_num == pe[p].lv_num) {
- flag = 1;
- break;
- }
- }
- if (flag == 0) {
- pe_this[pt_count].lv_num = pe[p].lv_num;
- for (pt = 0; pt < pv->pe_total; pt++)
- if (pe_this[pt_count].lv_num ==
- pe[pt].lv_num)
- pe_this_count[pt_count]++;
- pt_count++;
- }
- }
- }
+ /* FIXME prefix */
+ log_print("LV Name %s/%s", lv->vg->name, lv->name);
+ log_print("VG Name %s", lv->vg->name);
+
+ log_print("LV Write Access %s",
+ (lv->status & LVM_WRITE) ? "read/write" : "read only");
- lv = lvs;
- printf(" --- Distribution of physical volume ---\n"
- " LV Name LE of LV PE for LV\n");
- for (pt = 0; pt < pt_count; pt++) {
- printf(" %-25s ", lv->lv_name);
- if (strlen(lv->lv_name) > 25)
- printf("\n ");
- printf("%-8u %-8d\n",
- lv->lv_allocated_le,
- pe_this_count[pt]);
- if (pe_this[pt].lv_num > lv_num_last) {
- lv_num_last = pe_this[pt].lv_num;
- lv_names_sav = lv_names;
- if ((lv_names = dbg_realloc(lv_names,
- lv_num_last * NAME_LEN)) ==
- NULL) {
- log_error("realloc error in %s [line %d]",
- __FILE__, __LINE__);
- goto pv_display_pe_text_out;
- } else
- lv_names_sav = NULL;
+/******* FIXME Snapshot
+ if (lv->status & (LVM_SNAPSHOT_ORG | LVM_SNAPSHOT)) {
+ if (lvm_tab_vg_read_with_pv_and_lv(vg_name, &vg) < 0) {
+ ret = -LVM_ELV_SHOW_VG_READ_WITH_PV_AND_LV;
+ goto lv_show_end;
+ }
+ printf("LV snapshot status ");
+ if (vg_check_active(vg_name) == TRUE) {
+ vg_t *vg_core;
+ if ((ret = vg_status_with_pv_and_lv(vg_name, &vg_core)) == 0) {
+ lv_t *lv_ptr =
+ vg_core->
+ lv[lv_get_index_by_name(vg_core, lv->lv_name)];
+ if (lv_ptr->lv_access & LV_SNAPSHOT) {
+ if (lv_ptr->lv_status & LV_ACTIVE)
+ printf("active ");
+ else
+ printf("INACTIVE ");
+ }
+ if (lv_ptr->lv_access & LV_SNAPSHOT_ORG) {
+ printf("source of\n");
+ while (lv_ptr->lv_snapshot_next != NULL) {
+ lv_ptr = lv_ptr->lv_snapshot_next;
+ printf(" %s [%s]\n",
+ lv_ptr->lv_name,
+ (lv_ptr->
+ lv_status & LV_ACTIVE) ? "active" :
+ "INACTIVE");
+ }
+ vg_free(vg_core, TRUE);
+ } else {
+ printf("destination for %s\n",
+ lv_ptr->lv_snapshot_org->lv_name);
}
- strcpy(&lv_names[(pe_this[pt].lv_num - 1) * NAME_LEN],
- lv->lv_name);
- lv++;
+ }
+ } else {
+ printf("INACTIVE ");
+ if (lv->lv_access & LV_SNAPSHOT_ORG)
+ printf("original\n");
+ else
+ printf("snapshot\n");
}
+ }
+***********/
+
+ log_print("LV Status %savailable",
+ (lv->status & ACTIVE) ? "" : "NOT ");
+
+/********* FIXME lv_number
+ log_print("LV # %u", lv->lv_number + 1);
+************/
+
+/********* FIXME lv_open
+ log_print("# open %u\n", lv->lv_open);
+**********/
+/********
+#ifdef LVM_FUTURE
+ printf("Mirror copies %u\n", lv->lv_mirror_copies);
+ printf("Consistency recovery ");
+ if (lv->lv_recovery | LV_BADBLOCK_ON)
+ printf("bad blocks\n");
+ else
+ printf("none\n");
+ printf("Schedule %u\n", lv->lv_schedule);
+#endif
+********/
+
+
+ size = display_size(lv->size / 2, SIZE_SHORT);
+ log_print("LV Size %s", size);
+ dbg_free(size);
- printf("\n --- Physical extents ---\n"
- " PE LV LE Disk sector\n");
- pe_free = -1;
- for (p = 0; p < pv->pe_total; p++) {
- if (pe[p].lv_num != 0) {
- if (pe_free > -1) {
- pv_display_pe_free(pe_free, p);
- pe_free = -1;
- }
- lv_name_this = &lv_names[(pe[p].lv_num - 1) * NAME_LEN];
- printf(" %05d %-25s ", p, lv_name_this);
- if (strlen(lv_name_this) > 25)
- printf("\n ");
- printf("%05d %ld\n", pe[p].le_num,
- get_pe_offset(p, pv));
-
- } else if (pe_free == -1)
- pe_free = p;
+ log_print("Current LE %u", lv->le_count);
+
+/********** FIXME allocation
+ log_print("Allocated LE %u", lv->allocated_le);
+**********/
+
+/********** FIXME Snapshot
+ if (lv->lv_access & LV_SNAPSHOT) {
+ printf("snapshot chunk size %s\n",
+ (dummy = lvm_show_size(lv->lv_chunk_size / 2, SHORT)));
+ dbg_free(dummy);
+ dummy = NULL;
+ if (lv->lv_remap_end > 0) {
+ lv_remap_ptr = lv->lv_remap_ptr;
+ if (lv_remap_ptr > lv->lv_remap_end)
+ lv_remap_ptr = lv->lv_remap_end;
+ dummy = lvm_show_size(lv_remap_ptr *
+ lv->lv_chunk_size / 2, SHORT);
+ dummy1 = lvm_show_size(lv->lv_remap_end *
+ lv->lv_chunk_size / 2, SHORT);
+ printf("Allocated to snapshot %.2f%% [%s/%s]\n",
+ (float) lv_remap_ptr * 100 / lv->lv_remap_end,
+ dummy, dummy1);
+ dbg_free(dummy);
+ dbg_free(dummy1);
+ dummy =
+ lvm_show_size((vg->
+ lv[lv_get_index_by_number
+ (vg,
+ lv->lv_number)]->lv_size -
+ lv->lv_remap_end * lv->lv_chunk_size) / 2,
+ SHORT);
+ printf("Allocated to COW-table %s\n", dummy);
+ dbg_free(dummy);
}
+ }
+******************/
- if (pe_free > 0)
- pv_display_pe_free(pe_free, p);
+ if (lv->stripes > 1) {
+ log_print("Stripes %u", lv->stripes);
+/*********** FIXME stripesize
+ log_print("Stripe size (KByte) %u", lv->stripesize / 2);
+***********/
+ }
- pv_display_pe_text_out:
- if (lv_names != NULL)
- dbg_free(lv_names);
- else if (lv_names_sav != NULL)
- dbg_free(lv_names_sav);
- if (pe_this != NULL)
- dbg_free(pe_this);
- if (pe_this_count != NULL)
- dbg_free(pe_this_count);
- return;
-}
+/**************
+#ifdef LVM_FUTURE
+ printf("Bad block ");
+ if (lv->lv_badblock == LV_BADBLOCK_ON)
+ printf("on\n");
+ else
+ printf("off\n");
+#endif
+***************/
-void pv_display_pe_free(int pe_free, int p)
-{
- printf(" %05d free\n", pe_free);
+ alloc = lv->status & (ALLOC_STRICT | ALLOC_CONTIGUOUS);
+ log_print("Allocation %s%s%s%s",
+ !(alloc & (ALLOC_STRICT | ALLOC_CONTIGUOUS)) ? "next free" : "",
+ (alloc == ALLOC_STRICT) ? "strict" : "",
+ (alloc == ALLOC_CONTIGUOUS) ? "contiguous" : "",
+ (alloc == (ALLOC_STRICT | ALLOC_CONTIGUOUS)) ? "strict/contiguous" : ""
+ );
- if (p - pe_free > 1)
- printf(" .....\n %05d free\n", p - 1);
+ log_print("Read ahead sectors %u\n", lv->read_ahead);
- return;
-}
+/****************
+#ifdef LVM_FUTURE
+ printf("IO Timeout (seconds) ");
+ if (lv->lv_io_timeout == 0)
+ printf("default\n\n");
+ else
+ printf("%lu\n\n", lv->lv_io_timeout);
#endif
+*************/
+
+/********* FIXME blockdev
+ printf("Block device %d:%d\n",
+ MAJOR(lv->lv_dev), MINOR(lv->lv_dev));
+*************/
+
+ return;
+}
diff --git a/lib/log/log.h b/lib/log/log.h
index 0d9df41f..b422f0a4 100644
--- a/lib/log/log.h
+++ b/lib/log/log.h
@@ -65,7 +65,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
#define log_err(x...) plog(_LOG_ERR, x)
#define log_fatal(x...) plog(_LOG_FATAL, x)
-#define stack log_debug("stack")
+#define stack log_debug( "s" )
#define log_error(fmt, args...) log_err(fmt , ## args)
#define log_print(fmt, args...) log_warn(fmt , ## args)
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 77a76175..11db65b5 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -23,8 +23,10 @@ VPATH = @srcdir@
SOURCES=\
lvchange.c \
lvcreate.c \
+ lvdisplay.c \
lvm.c \
lvmchange.c \
+ lvreduce.c \
lvremove.c \
lvscan.c \
pvchange.c \
diff --git a/tools/lvdisplay.c b/tools/lvdisplay.c
new file mode 100644
index 00000000..8130a33d
--- /dev/null
+++ b/tools/lvdisplay.c
@@ -0,0 +1,86 @@
+/*
+ * 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 lvdisplay_single(char *lv_name);
+int lvdisplay(int argc, char **argv)
+{
+ int ret = 0;
+ int ret_max = 0;
+ int opt = 0;
+
+ /* FIXME Allow VG / all arguments via a process_each? */
+ if (!argc) {
+ log_error("Please enter one or more logical volume paths");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (arg_count(colon_ARG) && arg_count(verbose_ARG)) {
+ log_error("Options -v and -c are incompatible");
+ return EINVALID_CMD_LINE;
+ }
+
+ for (opt = 0; opt < argc; opt++) {
+ ret = lvdisplay_single(argv[opt]);
+ if (ret > ret_max)
+ ret_max = ret;
+ }
+
+ return ret_max;
+}
+
+int lvdisplay_single(char *lv_name)
+{
+ char *vg_name = NULL;
+
+ struct volume_group *vg;
+ struct list *lvh;
+ struct logical_volume *lv;
+
+ /* does VG exist? */
+ if (!(vg_name = extract_vgname(ios, lv_name))) {
+ return ECMD_FAILED;
+ }
+
+ 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 (!(lvh = find_lv_in_vg(vg, lv_name))) {
+ log_error("Can't find logical volume %s in volume group %s",
+ lv_name, vg_name);
+ return ECMD_FAILED;
+ }
+
+ lv = &list_item(lvh, struct lv_list)->lv;
+
+ if (arg_count(colon_ARG))
+ lvdisplay_colons(lv);
+ else {
+ lvdisplay_full(lv);
+ if (arg_count(verbose_ARG))
+ lvdisplay_extents(lv);
+ }
+
+ return 0;
+}
diff --git a/tools/lvreduce.c b/tools/lvreduce.c
new file mode 100644
index 00000000..e9163e5b
--- /dev/null
+++ b/tools/lvreduce.c
@@ -0,0 +1,183 @@
+/*
+ * 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 lvreduce(int argc, char **argv)
+{
+ struct volume_group *vg;
+ struct logical_volume *lv;
+ struct list *lvh;
+ int32_t extents = 0;
+ int32_t size = 0;
+ char *lv_name, *vg_name;
+ char *st;
+
+ 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))
+ extents = arg_int_value(extents_ARG, 0);
+
+ if (arg_count(size_ARG))
+ size = arg_int_value(size_ARG, 0);
+
+ 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 reduction",
+ lv_name);
+ return ECMD_FAILED;
+ }
+
+ if (size) {
+ /* No of 512-byte sectors */
+ extents = size * 2;
+
+ if (extents % vg->extent_size) {
+ char *s1;
+
+ extents += (signed) vg->extent_size -
+ (signed) (extents % vg->extent_size);
+ log_print("Rounding up size to full physical extent %s",
+ (s1 =
+ display_size(abs(extents) / 2, SIZE_SHORT)));
+ dbg_free(s1);
+ }
+
+ extents /= (signed) vg->extent_size;
+ }
+
+ if (!extents) {
+ log_error("New size of 0 not permitted");
+ return EINVALID_CMD_LINE;
+ }
+
+ if (extents < 0) {
+ if (1 - extents > lv->le_count) {
+ log_error("Unable to reduce %s below 1 extent",
+ lv_name);
+ return EINVALID_CMD_LINE;
+ }
+
+ lv->le_count += extents;
+ } else {
+ if (extents >= lv->le_count) {
+ log_error("New size given (%d extents) not less than "
+ "existing size (%d extents)", extents,
+ lv->le_count);
+ return EINVALID_CMD_LINE;
+ }
+ lv->le_count = extents;
+ }
+
+/************ FIXME Stripes
+ size_rest = new_size % (vg->lv[l]->lv_stripes * vg->pe_size);
+ if (size_rest != 0) {
+ log_print
+ ("rounding size %ld KB to stripe boundary size ",
+ new_size / 2);
+ new_size = new_size - size_rest;
+ printf("%ld KB\n", new_size / 2);
+ }
+***********************/
+
+ if (lv->status & ACTIVE || lv_active(lv) > 0) {
+ char *dummy;
+ 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,
+ SIZE_SHORT)));
+ log_print("THIS MAY DESTROY YOUR DATA (filesystem etc.)");
+ dbg_free(dummy);
+ }
+
+ if (!arg_count(force_ARG)) {
+ if (yes_no_prompt
+ ("Do you really want to reduce %s? [y/n]: ", lv_name)
+ == 'n') {
+ log_print("Logical volume %s NOT reduced", lv_name);
+ return ECMD_FAILED;
+ }
+ }
+
+/********* 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 reduced", lv_name);
+
+ return 0;
+}
+
diff --git a/tools/stub.h b/tools/stub.h
index 94ccc4f4..a8cfc955 100644
--- a/tools/stub.h
+++ b/tools/stub.h
@@ -19,12 +19,10 @@
*/
int e2fsadm(int argc, char **argv) {return 1;}
-int lvdisplay(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;}
-int lvreduce(int argc, char **argv) {return 1;}
int lvrename(int argc, char **argv) {return 1;}
int pvdata(int argc, char **argv) {return 1;}
int vgcfgbackup(int argc, char **argv) {return 1;}