summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-03-05 01:43:20 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-03-05 01:43:20 -0800
commit8bd28eea831fd5215c12e6fcecc8e9a772398ed9 (patch)
tree2579ba0d9921953cadfc17006c47ff419382898a /test
downloaddevice-mapper-8bd28eea831fd5215c12e6fcecc8e9a772398ed9.tar.gz
device-mapper-8bd28eea831fd5215c12e6fcecc8e9a772398ed9.tar.bz2
device-mapper-8bd28eea831fd5215c12e6fcecc8e9a772398ed9.zip
Imported Upstream version 2.02.79upstream/2.02.79
Diffstat (limited to 'test')
-rw-r--r--test/.gitignore4
-rw-r--r--test/Makefile.in130
-rw-r--r--test/api/Makefile.in61
-rw-r--r--test/api/percent.c64
-rw-r--r--test/api/percent.sh23
-rw-r--r--test/api/test.c1091
-rw-r--r--test/api/vgtest.c164
-rw-r--r--test/api/vgtest.sh18
-rw-r--r--test/check.sh198
-rw-r--r--test/harness.c221
-rw-r--r--test/harness.sh50
-rw-r--r--test/lvm-utils.sh153
-rwxr-xr-xtest/mkdtemp120
-rw-r--r--test/not.c65
-rwxr-xr-xtest/t-000-basic.sh30
-rw-r--r--test/t-activate-missing.sh87
-rw-r--r--test/t-activate-partial.sh30
-rwxr-xr-xtest/t-covercmd.sh82
-rw-r--r--test/t-dmeventd-restart.sh32
-rw-r--r--test/t-fsadm.sh123
-rw-r--r--test/t-inconsistent-metadata.sh75
-rw-r--r--test/t-listings.sh83
-rw-r--r--test/t-lock-blocking.sh36
-rw-r--r--test/t-lvchange-mirror.sh28
-rw-r--r--test/t-lvconvert-mirror-basic-0.sh12
-rw-r--r--test/t-lvconvert-mirror-basic-1.sh12
-rw-r--r--test/t-lvconvert-mirror-basic-2.sh12
-rw-r--r--test/t-lvconvert-mirror-basic-3.sh12
-rw-r--r--test/t-lvconvert-mirror-basic.sh148
-rw-r--r--test/t-lvconvert-mirror.sh242
-rw-r--r--test/t-lvconvert-repair-dmeventd.sh26
-rw-r--r--test/t-lvconvert-repair-policy.sh80
-rw-r--r--test/t-lvconvert-repair-replace.sh61
-rw-r--r--test/t-lvconvert-repair-transient.sh28
-rw-r--r--test/t-lvconvert-repair.sh89
-rw-r--r--test/t-lvconvert-twostep.sh21
-rw-r--r--test/t-lvcreate-mirror.sh39
-rw-r--r--test/t-lvcreate-operation.sh42
-rwxr-xr-xtest/t-lvcreate-pvtags.sh42
-rw-r--r--test/t-lvcreate-small-snap.sh30
-rwxr-xr-xtest/t-lvcreate-usage.sh141
-rwxr-xr-xtest/t-lvextend-percent-extents.sh101
-rw-r--r--test/t-lvextend-snapshot-dmeventd.sh51
-rw-r--r--test/t-lvextend-snapshot-policy.sh47
-rw-r--r--test/t-lvm-init.sh21
-rwxr-xr-xtest/t-lvmcache-exercise.sh23
-rw-r--r--test/t-lvresize-mirror.sh38
-rwxr-xr-xtest/t-lvresize-usage.sh20
-rwxr-xr-xtest/t-mdata-strings.sh33
-rwxr-xr-xtest/t-metadata-balance.sh232
-rwxr-xr-xtest/t-metadata.sh80
-rw-r--r--test/t-mirror-names.sh156
-rwxr-xr-xtest/t-mirror-vgreduce-removemissing.sh421
-rw-r--r--test/t-nomda-missing.sh83
-rwxr-xr-xtest/t-pool-labels.sh39
-rwxr-xr-xtest/t-pv-range-overflow.sh32
-rwxr-xr-xtest/t-pvchange-usage.sh66
-rwxr-xr-xtest/t-pvcreate-metadata0.sh32
-rw-r--r--test/t-pvcreate-operation-md.sh143
-rwxr-xr-xtest/t-pvcreate-operation.sh121
-rwxr-xr-xtest/t-pvcreate-usage.sh191
-rwxr-xr-xtest/t-pvmove-basic.sh374
-rwxr-xr-xtest/t-pvremove-usage.sh68
-rwxr-xr-xtest/t-read-ahead.sh62
-rw-r--r--test/t-snapshot-autoumount-dmeventd.sh41
-rwxr-xr-xtest/t-snapshot-merge.sh132
-rw-r--r--test/t-snapshots-of-mirrors.sh44
-rwxr-xr-xtest/t-tags.sh74
-rw-r--r--test/t-test-partition.sh30
-rw-r--r--test/t-topology-support.sh104
-rw-r--r--test/t-unknown-segment.sh34
-rw-r--r--test/t-unlost-pv.sh38
-rw-r--r--test/t-vgcfgbackup-usage.sh54
-rw-r--r--test/t-vgchange-maxlv.sh31
-rw-r--r--test/t-vgchange-usage.sh44
-rwxr-xr-xtest/t-vgcreate-usage.sh163
-rw-r--r--test/t-vgextend-restoremissing.sh30
-rw-r--r--test/t-vgextend-usage.sh129
-rwxr-xr-xtest/t-vgmerge-operation.sh81
-rwxr-xr-xtest/t-vgmerge-usage.sh73
-rwxr-xr-xtest/t-vgreduce-usage.sh85
-rwxr-xr-xtest/t-vgrename-usage.sh41
-rwxr-xr-xtest/t-vgsplit-operation.sh290
-rw-r--r--test/t-vgsplit-stacked.sh28
-rwxr-xr-xtest/t-vgsplit-usage.sh187
-rw-r--r--test/test-utils.sh457
86 files changed, 8629 insertions, 0 deletions
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..2351bfc
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,4 @@
+.bin-dir-stamp
+Makefile
+bin
+init.sh
diff --git a/test/Makefile.in b/test/Makefile.in
new file mode 100644
index 0000000..86542c1
--- /dev/null
+++ b/test/Makefile.in
@@ -0,0 +1,130 @@
+# Copyright (C) 2007-2010 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#TEST_OPTS=--verbose --debug
+SHELL_PATH ?= $(SHELL)
+TAR ?= $(TAR)
+RM ?= rm -f
+
+subdir := $(shell pwd|sed 's,.*/,,')
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
+abs_srcdir = @abs_srcdir@
+abs_builddir = @abs_builddir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+
+T ?= .
+S ?= @ # never match anything by default
+VERBOSE ?= 0
+RUN = $(shell find $(srcdir) -regextype posix-egrep \( -name t-\*.sh -or -path */api/\*.sh \) -and -regex "$(srcdir)/.*($(T)).*" -and -not -regex "$(srcdir)/.*($(S)).*" | sort)
+RUN_BASE = $(shell echo $(RUN) | xargs -n 1 echo | sed -e s,^$(srcdir)/,,)
+
+# Shell quote;
+SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+
+SUPPORT := $(srcdir)/test-utils.sh \
+ $(srcdir)/lvm-utils.sh
+
+ifeq ("@UDEV_SYNC@", "yes")
+dm_udev_synchronisation = 1
+endif
+
+all check: init.sh
+ make -C api tests
+ @echo Testing with locking_type 1
+ VERBOSE=$(VERBOSE) ./bin/harness $(RUN_BASE)
+ @echo Testing with locking_type 3
+ VERBOSE=$(VERBOSE) LVM_TEST_LOCKING=3 ./bin/harness $(RUN_BASE)
+
+check_cluster: init.sh
+ make -C api tests
+ @echo Testing with locking_type 3
+ VERBOSE=$(VERBOSE) LVM_TEST_LOCKING=3 ./bin/harness $(RUN_BASE)
+
+check_local: init.sh
+ make -C api tests
+ @echo Testing with locking_type 1
+ VERBOSE=$(VERBOSE) LVM_TEST_LOCKING=1 ./bin/harness $(RUN_BASE)
+
+bin/not: $(srcdir)/not.c .bin-dir-stamp
+ $(CC) -o bin/not $<
+ ln -sf not bin/should
+
+bin/harness: $(srcdir)/harness.c .bin-dir-stamp
+ $(CC) -o bin/harness $<
+
+bin/check: $(srcdir)/check.sh .bin-dir-stamp
+ cp $< bin/check
+ chmod +x bin/check
+
+init.sh: $(srcdir)/Makefile.in .bin-dir-stamp bin/not bin/check bin/harness $(RUN) $(SUPPORT) $(UNIT)
+ rm -f $@-t $@
+ echo 'top_srcdir=$(top_srcdir)' >> $@-t
+ echo 'abs_top_builddir=$(abs_top_builddir)' >> $@-t
+ echo 'abs_top_srcdir=$(abs_top_builddir)' >> $@-t
+ echo 'PATH=$$abs_top_builddir/test/bin:$$PATH' >> $@-t
+ LDLPATH="\$$abs_top_builddir/libdm"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/tools"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/liblvm"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/daemons/dmeventd"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/daemons/dmeventd/plugins/lvm2"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/daemons/dmeventd/plugins/mirror"; \
+ LDLPATH="$$LDLPATH:\$$abs_top_builddir/daemons/dmeventd/plugins/snapshot"; \
+ echo "export LD_LIBRARY_PATH=\"$$LDLPATH\"" >> $@-t
+ echo 'top_srcdir=$(top_srcdir)' >> $@-t
+ echo 'abs_srcdir=$(abs_srcdir)' >> $@-t
+ echo 'abs_builddir=$(abs_builddir)' >> $@-t
+ echo 'export PATH' >> $@-t
+ echo 'export DM_UDEV_SYNCHRONISATION=$(dm_udev_synchronisation)' >> $@-t
+ chmod a-w $@-t
+ mv $@-t $@
+ @if test "$(srcdir)" != . ; then \
+ echo "Copying tests to builddir."; \
+ cp $(SUPPORT) .; \
+ for f in $(RUN); do cp $$f `echo $$f | sed -e s,^$(srcdir)/,,`; done; \
+ fi
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+.bin-dir-stamp: lvm-wrapper
+ rm -rf bin
+ mkdir bin
+ for i in lvm $$(cat ../tools/.commands); do \
+ ln -s ../lvm-wrapper bin/$$i; \
+ done
+ ln -s "$(abs_top_builddir)/tools/dmsetup" bin/dmsetup
+ ln -s "$(abs_top_builddir)/daemons/clvmd/clvmd" bin/clvmd
+ ln -s "$(abs_top_builddir)/daemons/dmeventd/dmeventd" bin/dmeventd
+ touch $@
+
+lvm-wrapper: Makefile
+ rm -f $@-t $@
+ echo '#!/bin/sh' > $@-t
+ echo 'cmd=$$(echo ./$$0|sed "s,.*/,,")' >> $@-t
+ echo 'test "$$cmd" = lvm &&' >> $@-t
+ echo 'exec "$(abs_top_builddir)/tools/lvm" "$$@"' >> $@-t
+ echo 'exec "$(abs_top_builddir)/tools/lvm" "$$cmd" "$$@"' >> $@-t
+ chmod a-w,a+x $@-t
+ mv $@-t $@
+
+clean:
+ rm -rf init.sh lvm-wrapper bin .bin-dir-stamp
+ if test "$(srcdir)" != . ; then rm -f $(subst $(srcdir)/, ,$(RUN)) lvm2app.sh ; fi
+
+distclean: clean
+ rm -f Makefile
+
+.NOTPARALLEL:
diff --git a/test/api/Makefile.in b/test/api/Makefile.in
new file mode 100644
index 0000000..b3fb751
--- /dev/null
+++ b/test/api/Makefile.in
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
+
+ifeq ("@DEBUG@", "yes")
+ DEFS += -DDEBUG
+endif
+
+TARGETS =
+test_SOURCES = test.c
+wrapper_SOURCES = test.c
+INCLUDES += -I../../include
+
+UNIT = vgtest.t percent.t
+
+LVMLIBS = @LVM2APP_LIB@ -ldevmapper
+DEPLIBS = $(top_builddir)/liblvm/liblvm2app.so $(top_builddir)/libdm/libdevmapper.so
+
+DEFS += -D_REENTRANT
+
+include $(top_builddir)/make.tmpl
+
+LDFLAGS = -L$(top_builddir)/libdm -L$(top_builddir)/liblvm
+
+ifeq ("@DMEVENTD@", "yes")
+ LVMLIBS += -ldevmapper-event
+ LDFLAGS += -L$(top_builddir)/daemons/dmeventd
+endif
+
+test_OBJECTS = $(test_SOURCES:.c=.o)
+wrapper_OBJECTS = $(wrapper_SOURCES:.c=.o)
+OBJECTS = $(test_OBJECTS)
+
+all: tests test
+
+tests: $(UNIT)
+
+test: $(test_OBJECTS) $(DEPLIBS)
+ $(CC) -o test $(test_OBJECTS) $(CFLAGS) $(LDFLAGS) $(LVMLIBS) $(LIBS) $(READLINE_LIBS)
+
+%.t: %.o $(DEPLIBS)
+ $(CC) -o $@ $(<) $(CFLAGS) $(LDFLAGS) $(LVMLIBS) $(LIBS)
+
+wrapper: $(wrapper_OBJECTS) $(DEPLIBS)
+ $(CC) -o wrapper $(wrapper_OBJECTS) $(CFLAGS) $(LDFLAGS) $(LVMLIBS) $(LIBS) -lreadline
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status test/api/Makefile
diff --git a/test/api/percent.c b/test/api/percent.c
new file mode 100644
index 0000000..a3be1eb
--- /dev/null
+++ b/test/api/percent.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lvm2app.h"
+
+#define assert(x) do { if (!(x)) goto bad; } while (0)
+
+int main(int argc, char *argv[])
+{
+ lvm_t handle;
+ vg_t vg = NULL;
+ lv_t lv;
+ struct lvm_property_value v;
+
+ handle = lvm_init(NULL);
+ assert(handle);
+
+ vg = lvm_vg_open(handle, argv[1], "r", 0);
+ assert(vg);
+
+ lv = lvm_lv_from_name(vg, "snap");
+ assert(lv);
+
+ v = lvm_lv_get_property(lv, "snap_percent");
+ assert(v.is_valid);
+ assert(v.value.integer == PERCENT_0);
+
+ lv = lvm_lv_from_name(vg, "mirr");
+ assert(lv);
+
+ v = lvm_lv_get_property(lv, "copy_percent");
+ assert(v.is_valid);
+ assert(v.value.integer == PERCENT_100);
+
+ lv = lvm_lv_from_name(vg, "snap2");
+ assert(lv);
+
+ v = lvm_lv_get_property(lv, "snap_percent");
+ assert(v.is_valid);
+ assert(v.value.integer == 50 * PERCENT_1);
+
+ lvm_vg_close(vg);
+ return 0;
+
+bad:
+ if (handle && lvm_errno(handle))
+ fprintf(stderr, "LVM Error: %s\n", lvm_errmsg(handle));
+ if (vg)
+ lvm_vg_close(vg);
+ if (handle)
+ lvm_quit(handle);
+ return 1;
+}
diff --git a/test/api/percent.sh b/test/api/percent.sh
new file mode 100644
index 0000000..4362eb2
--- /dev/null
+++ b/test/api/percent.sh
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+aux prepare_devs 2
+vgcreate -c n -s 4k $vg $devs
+lvcreate -n foo $vg -l 5
+lvcreate -s -n snap $vg/foo -l 2 -c 4k
+lvcreate -s -n snap2 $vg/foo -l 6 -c 4k
+dd if=/dev/urandom of=$DM_DEV_DIR/$vg/snap2 count=1 bs=1024
+lvcreate -m 1 -n mirr $vg -l 1 --mirrorlog core
+lvs
+apitest percent $vg
diff --git a/test/api/test.c b/test/api/test.c
new file mode 100644
index 0000000..434baea
--- /dev/null
+++ b/test/api/test.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <readline/readline.h>
+
+#include "lvm2app.h"
+
+#define MAX_ARGS 64
+
+static int lvm_split(char *str, int *argc, char **argv, int max)
+{
+ char *b = str, *e;
+ *argc = 0;
+
+ while (*b) {
+ while (*b && isspace(*b))
+ b++;
+
+ if ((!*b) || ((*argc == 0)&&(*b == '#')))
+ break;
+
+ e = b;
+ while (*e && !isspace(*e))
+ e++;
+
+ argv[(*argc)++] = b;
+ if (!*e)
+ break;
+ *e++ = '\0';
+ b = e;
+ if (*argc == max)
+ break;
+ }
+
+ return *argc;
+}
+
+static void _show_help(void)
+{
+ printf("'lv_activate vgname lvname: "
+ "Activate an LV\n");
+ printf("'lv_deactivate vgname lvname: "
+ "Deactivate an LV\n");
+ printf("'vg_remove_lv vgname lvname': "
+ "Remove a LV\n");
+ printf("'vg_create_lv_linear vgname lvname size_in_bytes': "
+ "Create a linear LV\n");
+ printf("'scan_vgs': "
+ "Scan the system for LVM metadata\n");
+ printf("'list_vg_names': "
+ "List the names of the VGs that exist in the system\n");
+ printf("'list_vg_ids': "
+ "List the uuids of the VGs that exist in the system\n");
+ printf("'vg_list_pvs vgname': "
+ "List the PVs that exist in VG vgname\n");
+ printf("'pv_list_pvsegs pvname': "
+ "List the PV segments that exist in PV pvname\n");
+ printf("'vg_list_lvs vgname': "
+ "List the LVs that exist in VG vgname\n");
+ printf("'lv_list_lvsegs vgname lvname': "
+ "List the LV segments that exist in LV vgname/lvname\n");
+ printf("'vgs_open': "
+ "List the VGs that are currently open\n");
+ printf("'vgs': "
+ "List all VGs known to the system\n");
+ printf("'vg_extend vgname device: "
+ "Issue a lvm_vg_extend() API call on VG 'vgname'\n");
+ printf("'vg_reduce vgname device: "
+ "Issue a lvm_vg_reduce() API call on VG 'vgname'\n");
+ printf("'vg_open vgname ['r' | 'w']': "
+ "Issue a lvm_vg_open() API call on VG 'vgname'\n");
+ printf("'vg_close vgname': "
+ "Issue a lvm_vg_close() API call on VG 'vgname'\n");
+ printf("'vg_create vgname: "
+ "Issue a lvm_vg_create() to create VG 'vgname'\n");
+ printf("'vg_remove vgname: "
+ "Issue a lvm_vg_remove() to remove VG 'vgname'\n");
+ printf("'config_reload': "
+ "Issue a lvm_config_reload() API to reload LVM config\n");
+ printf("'config_override' device: "
+ "Issue a lvm_config_override() with accept device filter\n");
+ printf("'vg_get_tags vgname': "
+ "List the tags of a VG\n");
+ printf("'lv_get_property vgname lvname property_name': "
+ "Display the value of LV property\n");
+ printf("'vg_get_property vgname property_name': "
+ "Display the value of VG property\n");
+ printf("'pv_get_property pvname property_name': "
+ "Display the value of PV property\n");
+ printf("'vg_set_property vgname property_name': "
+ "Set the value of VG property\n");
+ printf("'lv_get_tags vgname lvname': "
+ "List the tags of a LV\n");
+ printf("'vg_{add|remove}_tag vgname tag': "
+ "Add/remove a tag from a VG\n");
+ printf("'lv_{add|remove}_tag vgname lvname tag': "
+ "Add/remove a tag from a LV\n");
+ printf("'vgname_from_devname device': "
+ "Lookup a vgname from a device name\n");
+ printf("'vgname_from_pvid pvid': "
+ "Lookup a vgname from a pvid\n");
+ printf("'lv_from_uuid vgname lvuuid': "
+ "Lookup an LV from an LV uuid\n");
+ printf("'lv_from_name vgname lvname': "
+ "Lookup an LV from an LV name\n");
+ printf("'pv_from_uuid vgname pvuuid': "
+ "Lookup an LV from an LV uuid\n");
+ printf("'pv_from_name vgname pvname': "
+ "Lookup an LV from an LV name\n");
+ printf("'quit': exit the program\n");
+}
+
+static struct dm_hash_table *_vgid_hash = NULL;
+static struct dm_hash_table *_vgname_hash = NULL;
+static struct dm_hash_table *_pvname_hash = NULL;
+static struct dm_hash_table *_lvname_hash = NULL;
+
+static void _hash_destroy_single(struct dm_hash_table **htable)
+{
+ if (htable && *htable) {
+ dm_hash_destroy(*htable);
+ *htable = NULL;
+ }
+}
+
+static void _hash_destroy(void)
+{
+ _hash_destroy_single(&_vgname_hash);
+ _hash_destroy_single(&_vgid_hash);
+ _hash_destroy_single(&_pvname_hash);
+ _hash_destroy_single(&_lvname_hash);
+}
+
+static int _hash_create(void)
+{
+ if (!(_vgname_hash = dm_hash_create(128)))
+ return 0;
+ if (!(_pvname_hash = dm_hash_create(128))) {
+ _hash_destroy_single(&_vgname_hash);
+ return 0;
+ }
+ if (!(_lvname_hash = dm_hash_create(128))) {
+ _hash_destroy_single(&_vgname_hash);
+ _hash_destroy_single(&_pvname_hash);
+ return 0;
+ }
+ if (!(_vgid_hash = dm_hash_create(128))) {
+ _hash_destroy_single(&_vgname_hash);
+ _hash_destroy_single(&_pvname_hash);
+ _hash_destroy_single(&_lvname_hash);
+ return 0;
+ }
+ return 1;
+}
+
+/* FIXME: this should be per vg */
+static lv_t _lookup_lv_by_name(const char *name)
+{
+ lv_t lv;
+
+ if (!name) {
+ printf ("Invalid LV name\n");
+ return NULL;
+ }
+ if (!(lv = dm_hash_lookup(_lvname_hash, name))) {
+ printf ("Can't find %s in LVs - run vg_create_lv first\n",
+ name);
+ return NULL;
+ }
+ return lv;
+}
+
+static vg_t _lookup_vg_by_name(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return NULL;
+ }
+ if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
+ !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
+ printf ("Can't find %s in open VGs - run vg_open first\n",
+ argv[1]);
+ return NULL;
+ }
+ return vg;
+}
+
+static pv_t _lookup_pv_by_name(const char *name)
+{
+ pv_t pv;
+
+ if (!(pv = dm_hash_lookup(_pvname_hash, name))) {
+ printf ("Can't find %s in open PVs - run vg_open first\n",
+ name);
+ return NULL;
+ }
+ return pv;
+}
+
+static void _add_lvs_to_lvname_hash(struct dm_list *lvs)
+{
+ struct lvm_lv_list *lvl;
+ dm_list_iterate_items(lvl, lvs) {
+ /* Concatenate VG name with LV name */
+ dm_hash_insert(_lvname_hash, lvm_lv_get_name(lvl->lv), lvl->lv);
+ }
+}
+
+static void _add_pvs_to_pvname_hash(struct dm_list *pvs)
+{
+ struct lvm_pv_list *pvl;
+ dm_list_iterate_items(pvl, pvs) {
+ dm_hash_insert(_pvname_hash, lvm_pv_get_name(pvl->pv), pvl->pv);
+ }
+}
+
+static void _remove_device_from_pvname_hash(struct dm_list *pvs, const char *name)
+{
+ struct lvm_pv_list *pvl;
+ dm_list_iterate_items(pvl, pvs) {
+ if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
+ dm_hash_remove(_pvname_hash, name);
+ }
+}
+static void _add_device_to_pvname_hash(struct dm_list *pvs, const char *name)
+{
+ struct lvm_pv_list *pvl;
+ dm_list_iterate_items(pvl, pvs) {
+ if (!strncmp(lvm_pv_get_name(pvl->pv), name, strlen(name)))
+ dm_hash_insert(_pvname_hash, name, pvl->pv);
+ }
+}
+
+static void _vg_reduce(char **argv, int argc, lvm_t libh)
+{
+ vg_t vg;
+ struct dm_list *pvs;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
+ !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
+ printf ("VG not open\n");
+ return;
+ }
+ if (lvm_vg_reduce(vg, argv[2])) {
+ printf("Error reducing %s by %s\n", argv[1], argv[2]);
+ return;
+ }
+
+ printf("Success reducing vg %s by %s\n", argv[1], argv[2]);
+
+ /*
+ * Add the device into the hashes for lookups
+ */
+ pvs = lvm_vg_list_pvs(vg);
+ if (pvs && !dm_list_empty(pvs))
+ _remove_device_from_pvname_hash(pvs, argv[2]);
+}
+
+/* Print "Error" or "Success" depending on lvm status */
+static int _lvm_status_to_pass_fail(int rc)
+{
+ if (rc)
+ printf("Error ");
+ else
+ printf("Success ");
+ return rc;
+}
+static void _config_override(char **argv, int argc, lvm_t libh)
+{
+ int rc;
+ char tmp[64];
+
+ if (argc < 2) {
+ printf ("Please enter device\n");
+ return;
+ }
+ snprintf(tmp, 63, "devices{filter=[\"a|%s|\", \"r|.*|\"]}", argv[1]);
+ rc = lvm_config_override(libh, tmp);
+ _lvm_status_to_pass_fail(rc);
+ printf("overriding LVM configuration\n");
+}
+
+static void _config_reload(char **argv, int argc, lvm_t libh)
+{
+ int rc;
+ rc = lvm_config_reload(libh);
+ _lvm_status_to_pass_fail(rc);
+ printf("reloading LVM configuration\n");
+}
+
+static void _vg_extend(char **argv, int argc, lvm_t libh)
+{
+ vg_t vg;
+ struct dm_list *pvs;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ if (!(vg = dm_hash_lookup(_vgid_hash, argv[1])) &&
+ !(vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
+ printf ("VG not open\n");
+ return;
+ }
+ if (lvm_vg_extend(vg, argv[2])) {
+ printf("Error extending %s with %s\n", argv[1], argv[2]);
+ return;
+ }
+
+ printf("Success extending vg %s with %s\n", argv[1], argv[2]);
+
+ /*
+ * Add the device into the hashes for lookups
+ */
+ pvs = lvm_vg_list_pvs(vg);
+ if (pvs && !dm_list_empty(pvs))
+ _add_device_to_pvname_hash(pvs, argv[2]);
+}
+
+static void _vg_open(char **argv, int argc, lvm_t libh)
+{
+ vg_t vg;
+ struct dm_list *lvs;
+ struct dm_list *pvs;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ if ((vg = dm_hash_lookup(_vgid_hash, argv[1])) ||
+ (vg = dm_hash_lookup(_vgname_hash, argv[1]))) {
+ printf ("VG already open\n");
+ return;
+ }
+ if (argc < 3)
+ vg = lvm_vg_open(libh, argv[1], "r", 0);
+ else
+ vg = lvm_vg_open(libh, argv[1], argv[2], 0);
+ if (!vg || !lvm_vg_get_name(vg)) {
+ printf("Error opening %s\n", argv[1]);
+ return;
+ }
+
+ printf("Success opening vg %s\n", argv[1]);
+ dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
+ dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
+
+ /*
+ * Add the LVs and PVs into the hashes for lookups
+ */
+ lvs = lvm_vg_list_lvs(vg);
+ if (lvs && !dm_list_empty(lvs))
+ _add_lvs_to_lvname_hash(lvs);
+ pvs = lvm_vg_list_pvs(vg);
+ if (pvs && !dm_list_empty(pvs))
+ _add_pvs_to_pvname_hash(pvs);
+}
+/* Lookup the vg and remove it from the vgname and vgid hashes */
+static vg_t _lookup_and_remove_vg(const char *vgname)
+{
+ vg_t vg=NULL;
+
+ if ((vg = dm_hash_lookup(_vgname_hash, vgname))) {
+ dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
+ dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
+ }
+ if (!vg && (vg = dm_hash_lookup(_vgid_hash, vgname))) {
+ dm_hash_remove(_vgid_hash, lvm_vg_get_uuid(vg));
+ dm_hash_remove(_vgname_hash, lvm_vg_get_name(vg));
+ }
+ return vg;
+}
+
+static void _vg_write(char **argv, int argc)
+{
+ vg_t vg;
+ int rc = 0;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ vg = _lookup_vg_by_name(argv, argc);
+ if (!vg) {
+ printf("Can't find vg_name %s\n", argv[1]);
+ return;
+ }
+ rc = lvm_vg_write(vg);
+ _lvm_status_to_pass_fail(rc);
+ printf("writing VG %s\n", lvm_vg_get_name(vg));
+}
+
+static void _vg_create(char **argv, int argc, lvm_t libh)
+{
+ vg_t vg;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ vg = lvm_vg_create(libh, argv[1]);
+ if (!vg || !lvm_vg_get_name(vg)) {
+ printf("Error creating %s\n", argv[1]);
+ return;
+ }
+
+ printf("Success creating vg %s\n", argv[1]);
+ dm_hash_insert(_vgname_hash, lvm_vg_get_name(vg), vg);
+ dm_hash_insert(_vgid_hash, lvm_vg_get_uuid(vg), vg);
+}
+
+static void _vg_remove(char **argv, int argc)
+{
+ vg_t vg;
+ int rc = 0;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ vg = _lookup_vg_by_name(argv, argc);
+ if (!vg) {
+ printf("Can't find vg_name %s\n", argv[1]);
+ return;
+ }
+ rc = lvm_vg_remove(vg);
+ _lvm_status_to_pass_fail(rc);
+ printf("removing VG\n");
+}
+
+static void _vg_close(char **argv, int argc)
+{
+ vg_t vg;
+ int rc = 0;
+
+ if (argc < 2) {
+ printf ("Please enter vg_name\n");
+ return;
+ }
+ vg = _lookup_and_remove_vg(argv[1]);
+ if (!vg) {
+ printf("Can't find vg_name %s\n", argv[1]);
+ return;
+ }
+ rc = lvm_vg_close(vg);
+ _lvm_status_to_pass_fail(rc);
+ printf("closing VG\n");
+}
+
+static void _show_one_vg(vg_t vg)
+{
+ printf("%s (%s): sz=%"PRIu64", free=%"PRIu64", #pv=%"PRIu64
+ ", seq#=%"PRIu64"\n",
+ lvm_vg_get_name(vg), lvm_vg_get_uuid(vg),
+ lvm_vg_get_size(vg), lvm_vg_get_free_size(vg),
+ lvm_vg_get_pv_count(vg), lvm_vg_get_seqno(vg));
+}
+
+static void _print_pv(pv_t pv)
+{
+ if (!pv)
+ return;
+ printf("%s (%s): size=%"PRIu64", free=%"PRIu64
+ ", dev_size=%"PRIu64", mda_count=%"PRIu64"\n",
+ lvm_pv_get_name(pv), lvm_pv_get_uuid(pv),
+ lvm_pv_get_size(pv), lvm_pv_get_free(pv),
+ lvm_pv_get_dev_size(pv),
+ lvm_pv_get_mda_count(pv));
+}
+
+static void _print_lv(vg_t vg, lv_t lv)
+{
+ if (!lv)
+ return;
+ printf("%s/%s (%s): size=%"PRIu64", %sACTIVE / %sSUSPENDED\n",
+ lvm_vg_get_name(vg),
+ lvm_lv_get_name(lv), lvm_lv_get_uuid(lv),
+ lvm_lv_get_size(lv),
+ lvm_lv_is_active(lv) ? "" : "IN",
+ lvm_lv_is_suspended(lv) ? "" : "NOT ");
+}
+
+static void _list_open_vgs(void)
+{
+ dm_hash_iter(_vgid_hash, (dm_hash_iterate_fn) _show_one_vg);
+}
+
+static void _pvs_in_vg(char **argv, int argc)
+{
+ struct dm_list *pvs;
+ struct lvm_pv_list *pvl;
+ vg_t vg;
+
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ pvs = lvm_vg_list_pvs(vg);
+ if (!pvs || dm_list_empty(pvs)) {
+ printf("No PVs in VG %s\n", lvm_vg_get_name(vg));
+ return;
+ }
+ printf("PVs in VG %s:\n", lvm_vg_get_name(vg));
+ dm_list_iterate_items(pvl, pvs) {
+ _print_pv(pvl->pv);
+ }
+}
+
+static void _print_property_value(const char *name,
+ struct lvm_property_value v)
+{
+ if (!v.is_valid)
+ printf("%s = INVALID\n", name);
+ else if (v.is_string)
+ printf("%s = %s\n", name, v.value.string);
+ else
+ printf("%s = %"PRIu64"\n", name, v.value.integer);
+}
+
+static void _pvsegs_in_pv(char **argv, int argc)
+{
+ struct dm_list *pvsegs;
+ struct lvm_pvseg_list *pvl;
+ pv_t pv;
+
+ if (!(pv = _lookup_pv_by_name(argv[1])))
+ return;
+ pvsegs = lvm_pv_list_pvsegs(pv);
+ if (!pvsegs || dm_list_empty(pvsegs)) {
+ printf("No PV segments in pv %s\n", argv[1]);
+ return;
+ }
+ printf("PV segments in pv %s:\n", argv[1]);
+ dm_list_iterate_items(pvl, pvsegs) {
+ struct lvm_property_value v;
+ v = lvm_pvseg_get_property(pvl->pvseg, "pvseg_start");
+ _print_property_value("pvseg_start", v);
+ v = lvm_pvseg_get_property(pvl->pvseg, "pvseg_size");
+ _print_property_value("pvseg_size", v);
+ }
+}
+
+static void _scan_vgs(lvm_t libh)
+{
+ lvm_scan(libh);
+}
+
+static void _list_vg_names(lvm_t libh)
+{
+ struct dm_list *list;
+ struct lvm_str_list *strl;
+
+ list = lvm_list_vg_names(libh);
+ printf("VG names:\n");
+ dm_list_iterate_items(strl, list) {
+ printf("%s\n", strl->str);
+ }
+}
+
+static void _list_vg_ids(lvm_t libh)
+{
+ struct dm_list *list;
+ struct lvm_str_list *strl;
+
+ list = lvm_list_vg_uuids(libh);
+ printf("VG uuids:\n");
+ dm_list_iterate_items(strl, list) {
+ printf("%s\n", strl->str);
+ }
+}
+
+static void _display_tags(struct dm_list *list)
+{
+ struct lvm_str_list *strl;
+ if (dm_list_empty(list)) {
+ printf("No tags exist\n");
+ return;
+ } else if (!list) {
+ printf("Error obtaining tags\n");
+ return;
+ }
+ dm_list_iterate_items(strl, list) {
+ printf("%s\n", strl->str);
+ }
+}
+
+static void _vg_get_tags(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ printf("VG tags:\n");
+ _display_tags(lvm_vg_get_tags(vg));
+}
+
+static void _vg_tag(char **argv, int argc, int add)
+{
+ vg_t vg;
+
+ if (argc < 3) {
+ printf("Please enter vgname, tag\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ if (add && lvm_vg_add_tag(vg, argv[2]))
+ printf("Error ");
+ else if (!add && lvm_vg_remove_tag(vg, argv[2])){
+ printf("Error ");
+ } else {
+ printf("Success ");
+ }
+ printf("%s tag %s to VG %s\n",
+ add ? "adding":"removing", argv[2], argv[1]);
+}
+
+static void _pv_get_property(char **argv, int argc)
+{
+ pv_t pv;
+ struct lvm_property_value v;
+
+ if (argc < 3) {
+ printf("Please enter pvname, field_id\n");
+ return;
+ }
+ if (!(pv = _lookup_pv_by_name(argv[1])))
+ return;
+ v = lvm_pv_get_property(pv, argv[2]);
+ _print_property_value(argv[2], v);
+}
+
+static void _vg_get_property(char **argv, int argc)
+{
+ vg_t vg;
+ struct lvm_property_value v;
+
+ if (argc < 3) {
+ printf("Please enter vgname, field_id\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ v = lvm_vg_get_property(vg, argv[2]);
+ _print_property_value(argv[2], v);
+}
+
+static void _lv_get_property(char **argv, int argc)
+{
+ lv_t lv;
+ struct lvm_property_value v;
+
+ if (argc < 4) {
+ printf("Please enter vgname, lvname, field_id\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ v = lvm_lv_get_property(lv, argv[3]);
+ _print_property_value(argv[3], v);
+}
+
+static void _vg_set_property(char **argv, int argc)
+{
+ vg_t vg;
+ struct lvm_property_value value;
+ int rc;
+
+ if (argc < 4) {
+ printf("Please enter vgname, field_id, value\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ value = lvm_vg_get_property(vg, argv[2]);
+ if (!value.is_valid) {
+ printf("Error obtaining property value\n");
+ return;
+ }
+ if (value.is_string)
+ value.value.string = argv[3];
+ else
+ value.value.integer = atoi(argv[3]);
+ rc = lvm_vg_set_property(vg, argv[2], &value);
+ if (rc)
+ printf("Error ");
+ else
+ printf("Success ");
+ printf("setting value of property %s in VG %s\n",
+ argv[2], argv[1]);
+}
+
+static void _lv_get_tags(char **argv, int argc)
+{
+ lv_t lv;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lvname\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ printf("LV tags:\n");
+ _display_tags(lvm_lv_get_tags(lv));
+}
+
+static void _lv_tag(char **argv, int argc, int add)
+{
+ lv_t lv;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lvname\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ if (add && lvm_lv_add_tag(lv, argv[3]))
+ printf("Error ");
+ else if (!add && lvm_lv_remove_tag(lv, argv[3])){
+ printf("Error ");
+ } else {
+ printf("Success ");
+ }
+ printf("%s tag %s to LV %s\n",
+ add ? "adding":"removing", argv[3], argv[2]);
+}
+
+static void _lv_from_uuid(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lv_uuid\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ _print_lv(vg, lvm_lv_from_uuid(vg, argv[2]));
+}
+
+static void _lv_from_name(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lv_uuid\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ _print_lv(vg, lvm_lv_from_name(vg, argv[2]));
+}
+
+static void _pv_from_uuid(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (argc < 3) {
+ printf("Please enter vgname, pv_uuid\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ _print_pv(lvm_pv_from_uuid(vg, argv[2]));
+}
+
+static void _pv_from_name(char **argv, int argc)
+{
+ vg_t vg;
+
+ if (argc < 3) {
+ printf("Please enter vgname, pv_uuid\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ _print_pv(lvm_pv_from_name(vg, argv[2]));
+}
+
+static void _vgname_from_pvid(char **argv, int argc, lvm_t libh)
+{
+ const char *vgname;
+
+ if (argc < 1) {
+ printf("Please enter pvid\n");
+ return;
+ }
+ if (!(vgname = lvm_vgname_from_pvid(libh, argv[1]))) {
+ printf("Error ");
+ } else {
+ printf("Success ");
+ }
+ printf("looking up vgname=%s from PVID=%s\n",
+ vgname, argv[1]);
+}
+static void _vgname_from_devname(char **argv, int argc, lvm_t libh)
+{
+ const char *vgname;
+
+ if (argc < 1) {
+ printf("Please enter device\n");
+ return;
+ }
+ if (!(vgname = lvm_vgname_from_device(libh, argv[1]))) {
+ printf("Error ");
+ } else {
+ printf("Success ");
+ }
+ printf("looking up vgname=%s from device name=%s\n",
+ vgname, argv[1]);
+}
+static void _lvs_in_vg(char **argv, int argc)
+{
+ struct dm_list *lvs;
+ struct lvm_lv_list *lvl;
+ vg_t vg;
+
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ lvs = lvm_vg_list_lvs(vg);
+ if (!lvs || dm_list_empty(lvs)) {
+ printf("No LVs in VG %s\n", lvm_vg_get_name(vg));
+ return;
+ }
+ printf("LVs in VG %s:\n", lvm_vg_get_name(vg));
+ dm_list_iterate_items(lvl, lvs) {
+ _print_lv(vg, lvl->lv);
+ }
+}
+
+static void _lvsegs_in_lv(char **argv, int argc)
+{
+ struct dm_list *lvsegs;
+ struct lvm_lvseg_list *lvl;
+ lv_t lv;
+
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ lvsegs = lvm_lv_list_lvsegs(lv);
+ if (!lvsegs || dm_list_empty(lvsegs)) {
+ printf("No LV segments in lv %s\n", lvm_lv_get_name(lv));
+ return;
+ }
+ printf("LV segments in lv %s:\n", lvm_lv_get_name(lv));
+ dm_list_iterate_items(lvl, lvsegs) {
+ struct lvm_property_value v;
+ v = lvm_lvseg_get_property(lvl->lvseg, "segtype");
+ _print_property_value("segtype", v);
+ v = lvm_lvseg_get_property(lvl->lvseg, "seg_start_pe");
+ _print_property_value("seg_start_pe", v);
+ v = lvm_lvseg_get_property(lvl->lvseg, "seg_size");
+ _print_property_value("seg_size", v);
+ }
+}
+
+static void _lv_deactivate(char **argv, int argc)
+{
+ lv_t lv;
+ int rc=0;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lvname\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ rc = lvm_lv_deactivate(lv);
+ _lvm_status_to_pass_fail(rc);
+ printf("De-activating LV %s in VG %s\n",
+ argv[2], argv[1]);
+}
+static void _lv_activate(char **argv, int argc)
+{
+ lv_t lv;
+ int rc=0;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lvname\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ rc = lvm_lv_activate(lv);
+ _lvm_status_to_pass_fail(rc);
+ printf("activating LV %s in VG %s\n",
+ argv[2], argv[1]);
+}
+
+static void _vg_remove_lv(char **argv, int argc)
+{
+ lv_t lv;
+
+ if (argc < 3) {
+ printf("Please enter vgname, lvname\n");
+ return;
+ }
+ if (!(lv = _lookup_lv_by_name(argv[2])))
+ return;
+ if (lvm_vg_remove_lv(lv))
+ printf("Error ");
+ else {
+ printf("Success ");
+ dm_hash_remove(_lvname_hash, argv[2]);
+ }
+ printf("removing LV %s in VG %s\n",
+ argv[2], argv[1]);
+}
+
+static void _vg_create_lv_linear(char **argv, int argc)
+{
+ vg_t vg;
+ lv_t lv;
+
+ if (argc < 4) {
+ printf("Please enter vgname, lvname, and size\n");
+ return;
+ }
+ if (!(vg = _lookup_vg_by_name(argv, argc)))
+ return;
+ lv = lvm_vg_create_lv_linear(vg, argv[2], atol(argv[3]));
+ if (!lv)
+ printf("Error ");
+ else {
+ printf("Success ");
+ dm_hash_insert(_lvname_hash, argv[2], lv);
+ }
+ printf("creating LV %s in VG %s\n",
+ argv[2], argv[1]);
+}
+
+static int lvmapi_test_shell(lvm_t libh)
+{
+ int argc;
+ char *input = NULL, *args[MAX_ARGS], **argv;
+
+ _hash_create();
+ argc=0;
+ while (1) {
+ free(input);
+ input = readline("liblvm> ");
+
+ /* EOF */
+ if (!input) {
+ printf("\n");
+ break;
+ }
+
+ /* empty line */
+ if (!*input)
+ continue;
+
+ argv = args;
+
+ if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
+ printf("Too many arguments, sorry.");
+ continue;
+ }
+
+ if (!strcmp(argv[0], "lvm")) {
+ argv++;
+ argc--;
+ }
+
+ if (!argc)
+ continue;
+
+ if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
+ printf("Exiting.\n");
+ break;
+ } else if (!strcmp(argv[0], "?") || !strcmp(argv[0], "help")) {
+ _show_help();
+ } else if (!strcmp(argv[0], "config_reload")) {
+ _config_reload(argv, argc, libh);
+ } else if (!strcmp(argv[0], "config_override")) {
+ _config_override(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vg_extend")) {
+ _vg_extend(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vg_reduce")) {
+ _vg_reduce(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vg_write")) {
+ _vg_write(argv, argc);
+ } else if (!strcmp(argv[0], "vg_open")) {
+ _vg_open(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vg_close")) {
+ _vg_close(argv, argc);
+ } else if (!strcmp(argv[0], "vg_create")) {
+ _vg_create(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vg_remove")) {
+ _vg_remove(argv, argc);
+ } else if (!strcmp(argv[0], "lv_activate")) {
+ _lv_activate(argv, argc);
+ } else if (!strcmp(argv[0], "lv_deactivate")) {
+ _lv_deactivate(argv, argc);
+ } else if (!strcmp(argv[0], "vg_remove_lv")) {
+ _vg_remove_lv(argv, argc);
+ } else if (!strcmp(argv[0], "vgs_open")) {
+ _list_open_vgs();
+ } else if (!strcmp(argv[0], "vg_list_pvs")) {
+ _pvs_in_vg(argv, argc);
+ } else if (!strcmp(argv[0], "pv_list_pvsegs")) {
+ _pvsegs_in_pv(argv, argc);
+ } else if (!strcmp(argv[0], "vg_list_lvs")) {
+ _lvs_in_vg(argv, argc);
+ } else if (!strcmp(argv[0], "lv_list_lvsegs")) {
+ _lvsegs_in_lv(argv, argc);
+ } else if (!strcmp(argv[0], "list_vg_names")) {
+ _list_vg_names(libh);
+ } else if (!strcmp(argv[0], "list_vg_ids")) {
+ _list_vg_ids(libh);
+ } else if (!strcmp(argv[0], "scan_vgs")) {
+ _scan_vgs(libh);
+ } else if (!strcmp(argv[0], "vg_create_lv_linear")) {
+ _vg_create_lv_linear(argv, argc);
+ } else if (!strcmp(argv[0], "vg_add_tag")) {
+ _vg_tag(argv, argc, 1);
+ } else if (!strcmp(argv[0], "vg_remove_tag")) {
+ _vg_tag(argv, argc, 0);
+ } else if (!strcmp(argv[0], "vg_get_tags")) {
+ _vg_get_tags(argv, argc);
+ } else if (!strcmp(argv[0], "lv_get_property")) {
+ _lv_get_property(argv, argc);
+ } else if (!strcmp(argv[0], "vg_get_property")) {
+ _vg_get_property(argv, argc);
+ } else if (!strcmp(argv[0], "pv_get_property")) {
+ _pv_get_property(argv, argc);
+ } else if (!strcmp(argv[0], "vg_set_property")) {
+ _vg_set_property(argv, argc);
+ } else if (!strcmp(argv[0], "lv_add_tag")) {
+ _lv_tag(argv, argc, 1);
+ } else if (!strcmp(argv[0], "lv_remove_tag")) {
+ _lv_tag(argv, argc, 0);
+ } else if (!strcmp(argv[0], "lv_get_tags")) {
+ _lv_get_tags(argv, argc);
+ } else if (!strcmp(argv[0], "vgname_from_devname")) {
+ _vgname_from_devname(argv, argc, libh);
+ } else if (!strcmp(argv[0], "vgname_from_pvid")) {
+ _vgname_from_pvid(argv, argc, libh);
+ } else if (!strcmp(argv[0], "lv_from_uuid")) {
+ _lv_from_uuid(argv, argc);
+ } else if (!strcmp(argv[0], "lv_from_name")) {
+ _lv_from_name(argv, argc);
+ } else if (!strcmp(argv[0], "pv_from_uuid")) {
+ _pv_from_uuid(argv, argc);
+ } else if (!strcmp(argv[0], "pv_from_name")) {
+ _pv_from_name(argv, argc);
+ } else {
+ printf ("Unrecognized command %s\n", argv[0]);
+ }
+ }
+
+ dm_hash_iter(_vgname_hash, (dm_hash_iterate_fn) lvm_vg_close);
+ _hash_destroy();
+ free(input);
+ return 0;
+}
+
+int main (int argc, char *argv[])
+{
+ lvm_t libh;
+
+ libh = lvm_init(NULL);
+ if (!libh) {
+ printf("Unable to open lvm library instance\n");
+ return 1;
+ }
+
+ printf("Library version: %s\n", lvm_library_get_version());
+ lvmapi_test_shell(libh);
+
+ lvm_quit(libh);
+ return 0;
+}
+
diff --git a/test/api/vgtest.c b/test/api/vgtest.c
new file mode 100644
index 0000000..cb35da3
--- /dev/null
+++ b/test/api/vgtest.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Unit test case for vgcreate and related APIs.
+ * # gcc -g vgcreate.c -I../../liblvm -I../../include -L../../liblvm \
+ * -L../../libdm -ldevmapper -llvm2app
+ * # export LD_LIBRARY_PATH=`pwd`/../../libdm:`pwd`/../../liblvm
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "lvm2app.h"
+
+lvm_t handle;
+vg_t vg;
+const char *vg_name;
+#define MAX_DEVICES 16
+const char *device[MAX_DEVICES];
+uint64_t size = 1024;
+
+#define vg_create(vg_name) \
+ printf("Creating VG %s\n", vg_name); \
+ vg = lvm_vg_create(handle, vg_name); \
+ if (!vg) { \
+ fprintf(stderr, "Error creating volume group %s\n", vg_name); \
+ goto bad; \
+ }
+#define vg_extend(vg, dev) \
+ printf("Extending VG %s by %s\n", vg_name, dev); \
+ status = lvm_vg_extend(vg, dev); \
+ if (status) { \
+ fprintf(stderr, "Error extending volume group %s " \
+ "with device %s\n", vg_name, dev); \
+ goto bad; \
+ }
+#define vg_commit(vg) \
+ printf("Committing VG %s to disk\n", vg_name); \
+ status = lvm_vg_write(vg); \
+ if (status) { \
+ fprintf(stderr, "Commit of volume group '%s' failed\n", \
+ lvm_vg_get_name(vg)); \
+ goto bad; \
+ }
+#define vg_open(vg_name, mode) \
+ printf("Opening VG %s %s\n", vg_name, mode); \
+ vg = lvm_vg_open(handle, vg_name, mode, 0); \
+ if (!vg) { \
+ fprintf(stderr, "Error opening volume group %s\n", vg_name); \
+ goto bad; \
+ }
+#define vg_close(vg) \
+ printf("Closing VG %s\n", vg_name); \
+ if (lvm_vg_close(vg)) { \
+ fprintf(stderr, "Error closing volume group %s\n", vg_name); \
+ goto bad; \
+ }
+#define vg_reduce(vg, dev) \
+ printf("Reducing VG %s by %s\n", vg_name, dev); \
+ status = lvm_vg_reduce(vg, dev); \
+ if (status) { \
+ fprintf(stderr, "Error reducing volume group %s " \
+ "by device %s\n", vg_name, dev); \
+ goto bad; \
+ }
+#define vg_remove(vg) \
+ printf("Removing VG %s from system\n", vg_name); \
+ status = lvm_vg_remove(vg); \
+ if (status) { \
+ fprintf(stderr, "Revmoval of volume group '%s' failed\n", \
+ vg_name); \
+ goto bad; \
+ }
+
+static int init_vgtest(int argc, char *argv[])
+{
+ int i;
+
+ if (argc < 4) {
+ fprintf(stderr, "Usage: %s <vgname> <pv1> <pv2> [... <pvN> ]",
+ argv[0]);
+ return -1;
+ }
+ vg_name = argv[1];
+ for(i=2; i<MAX_DEVICES && i < argc; i++) {
+ device[i-2] = argv[i];
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int status;
+
+ if (init_vgtest(argc, argv) < 0)
+ goto bad;
+
+ /* FIXME: make the below messages verbose-only and print PASS/FAIL*/
+ printf("Opening LVM\n");
+ handle = lvm_init(NULL);
+ if (!handle) {
+ fprintf(stderr, "Unable to lvm_init\n");
+ goto bad;
+ }
+
+ printf("Library version: %s\n", lvm_library_get_version());
+ vg_create(vg_name);
+ vg_extend(vg, device[0]);
+
+ printf("Setting VG %s extent_size to %"PRIu64"\n", vg_name, size);
+ status = lvm_vg_set_extent_size(vg, size);
+ if (status) {
+ fprintf(stderr, "Can not set physical extent "
+ "size '%"PRIu64"' for '%s'\n",
+ size, vg_name);
+ goto bad;
+ }
+
+ vg_commit(vg);
+ vg_close(vg);
+
+ vg_open(vg_name, "r");
+ vg_close(vg);
+
+ vg_open(vg_name, "w");
+ vg_extend(vg, device[1]);
+ vg_reduce(vg, device[0]);
+ vg_commit(vg);
+ vg_close(vg);
+
+ vg_open(vg_name, "w");
+ vg_extend(vg, device[0]);
+ vg_commit(vg);
+ vg_close(vg);
+
+ vg_open(vg_name, "w");
+ vg_remove(vg);
+ vg_commit(vg);
+ vg_close(vg);
+
+ lvm_quit(handle);
+ printf("liblvm vgcreate unit test PASS\n");
+ _exit(0);
+bad:
+ printf("liblvm vgcreate unit test FAIL\n");
+ if (handle && lvm_errno(handle))
+ fprintf(stderr, "LVM Error: %s\n", lvm_errmsg(handle));
+ if (vg)
+ lvm_vg_close(vg);
+ if (handle)
+ lvm_quit(handle);
+ _exit(-1);
+}
diff --git a/test/api/vgtest.sh b/test/api/vgtest.sh
new file mode 100644
index 0000000..35daa44
--- /dev/null
+++ b/test/api/vgtest.sh
@@ -0,0 +1,18 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# tests lvm2app library
+#
+
+. ./test-utils.sh
+aux prepare_devs 2
+pvcreate $dev1 $dev2
+apitest vgtest $vg1 $dev1 $dev2
diff --git a/test/check.sh b/test/check.sh
new file mode 100644
index 0000000..843ce86
--- /dev/null
+++ b/test/check.sh
@@ -0,0 +1,198 @@
+#!/bin/bash
+
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# check.sh: assert various things about volumes
+
+# USAGE
+# check linear VG LV
+# check lv_on VG LV PV
+
+# check mirror VG LV [LOGDEV|core]
+# check mirror_nonredundant VG LV
+# check mirror_legs VG LV N
+# check mirror_images_on VG LV DEV [DEV...]
+
+# ...
+
+set -e -o pipefail
+
+lvl() {
+ lvs -a --noheadings "$@"
+}
+
+lvdevices() {
+ lvl -odevices "$@" | sed 's/([^)]*)//g; s/,/ /g'
+}
+
+mirror_images_redundant()
+{
+ vg=$1
+ lv=$vg/$2
+
+ lvs -a $vg -o+devices
+ for i in `lvdevices $lv`; do
+ echo "# $i:"
+ lvdevices $vg/$i | sort | uniq
+ done > check.tmp.all
+
+ (grep -v ^# check.tmp.all || true) | sort | uniq -d > check.tmp
+
+ test "`cat check.tmp | wc -l`" -eq 0 || {
+ echo "mirror images of $lv expected redundant, but are not:"
+ cat check.tmp.all
+ exit 1
+ }
+}
+
+mirror_images_on() {
+ vg=$1
+ lv=$2
+
+ shift 2
+
+ for i in `lvdevices $lv`; do
+ lv_on $vg $lv $1
+ shift
+ done
+}
+
+lv_on()
+{
+ lv="$1/$2"
+ lvdevices $lv | grep -F "$3" || {
+ echo "LV $lv expected on $3 but is not:" >&2
+ lvdevices $lv >&2
+ exit 1
+ }
+ test `lvdevices $lv | grep -vF "$3" | wc -l` -eq 0 || {
+ echo "LV $lv contains unexpected devices:" >&2
+ lvdevices $lv >&2
+ exit 1
+ }
+}
+
+mirror_log_on()
+{
+ vg="$1"
+ lv="$2"
+ where="$3"
+ if test "$where" = "core"; then
+ lvl -omirror_log "$vg/$lv" | not grep mlog
+ else
+ lv_on $vg "${lv}_mlog" "$where"
+ fi
+}
+
+lv_is_contiguous()
+{
+ test `lvl --segments $1 | wc -l` -eq 1 || {
+ echo "LV $1 expected to be contiguous, but is not:"
+ lvl --segments $1
+ exit 1
+ }
+}
+
+lv_is_clung()
+{
+ test `lvdevices $1 | sort | uniq | wc -l` -eq 1 || {
+ echo "LV $1 expected to be clung, but is not:"
+ lvdevices $! | sort | uniq
+ exit 1
+ }
+}
+
+mirror_images_contiguous()
+{
+ for i in `lvdevices $1/$2`; do
+ lv_is_contiguous $1/$i
+ done
+}
+
+mirror_images_clung()
+{
+ for i in `lvdevices $1/$2`; do
+ lv_is_clung $1/$i
+ done
+}
+
+mirror() {
+ mirror_nonredundant "$@"
+ mirror_images_redundant "$1" "$2"
+}
+
+mirror_nonredundant() {
+ lv="$1/$2"
+ lvs -oattr "$lv" | grep -q "^ *m.....$" || {
+ echo "$lv expected a mirror, but is not:"
+ lvs -a $lv
+ exit 1
+ }
+ if test -n "$3"; then mirror_log_on "$1" "$2" "$3"; fi
+}
+
+mirror_legs() {
+ lv="$1/$2"
+ expect="$3"
+ lvdevices "$lv"
+ real=`lvdevices "$lv" | wc -w`
+ test "$expect" = "$real"
+}
+
+mirror_no_temporaries()
+{
+ vg=$1
+ lv=$2
+ lvl -oname $vg | grep $lv | not grep "tmp" || {
+ echo "$lv has temporary mirror images unexpectedly:"
+ lvl $vg | grep $lv
+ exit 1
+ }
+}
+
+linear() {
+ lv="$1/$2"
+ lvl -ostripes "$lv" | grep -q "1" || {
+ echo "$lv expected linear, but is not:"
+ lvl "$lv" -o+devices
+ exit 1
+ }
+}
+
+active() {
+ lv="$1/$2"
+ lvl -oattr "$lv" 2> /dev/null | grep -q "^ *....a.$" || {
+ echo "$lv expected active, but lvs says it's not:"
+ lvl "$lv" -o+devices 2>/dev/null
+ exit 1
+ }
+ dmsetup table | egrep -q "$1-$2: *[^ ]+" || {
+ echo "$lv expected active, lvs thinks it is but there are no mappings!"
+ dmsetup table | grep $1-$2:
+ exit 1
+ }
+}
+
+inactive() {
+ lv="$1/$2"
+ lvl -oattr "$lv" 2> /dev/null | grep -q '^ *....[-isd].$' || {
+ echo "$lv expected inactive, but lvs says it's not:"
+ lvl "$lv" -o+devices 2>/dev/null
+ exit 1
+ }
+ dmsetup table | not egrep -q "$1-$2: *[^ ]+" || {
+ echo "$lv expected inactive, lvs thinks it is but there are mappings!"
+ dmsetup table | grep $1-$2:
+ exit 1
+ }
+}
+
+"$@"
diff --git a/test/harness.c b/test/harness.c
new file mode 100644
index 0000000..0162278
--- /dev/null
+++ b/test/harness.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+pid_t pid;
+int fds[2];
+
+#define MAX 1024
+
+struct stats {
+ int nfailed;
+ int nskipped;
+ int npassed;
+ int nwarned;
+ int status[MAX];
+};
+
+struct stats s;
+
+char *readbuf = NULL;
+int readbuf_sz = 0, readbuf_used = 0;
+
+int die = 0;
+int verbose = 0;
+
+#define PASSED 0
+#define SKIPPED 1
+#define FAILED 2
+#define WARNED 3
+
+void handler( int s ) {
+ signal( s, SIG_DFL );
+ kill( pid, s );
+ die = s;
+}
+
+void dump() {
+ fwrite(readbuf, 1, readbuf_used, stdout);
+}
+
+void clear() {
+ readbuf_used = 0;
+}
+
+void drain() {
+ int sz;
+ char buf[2048];
+ while (1) {
+ sz = read(fds[1], buf, 2048);
+ if (verbose)
+ write(1, buf, sz);
+ if (sz <= 0)
+ return;
+ if (readbuf_used + sz >= readbuf_sz) {
+ readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 4096;
+ readbuf = realloc(readbuf, readbuf_sz);
+ }
+ if (!readbuf)
+ exit(205);
+ memcpy(readbuf + readbuf_used, buf, sz);
+ readbuf_used += sz;
+ readbuf[readbuf_used] = 0;
+ }
+}
+
+void passed(int i, char *f) {
+ if (strstr(readbuf, "TEST WARNING")) {
+ ++s.nwarned;
+ s.status[i] = WARNED;
+ printf("warnings\n");
+ } else {
+ ++ s.npassed;
+ s.status[i] = PASSED;
+ printf("passed.\n");
+ }
+}
+
+void skipped(int i, char *f) {
+ ++ s.nskipped;
+ s.status[i] = SKIPPED;
+ printf("skipped.\n");
+}
+
+void failed(int i, char *f, int st) {
+ ++ s.nfailed;
+ s.status[i] = FAILED;
+ if(die == 2) {
+ printf("interrupted.\n");
+ return;
+ }
+ printf("FAILED.\n");
+ printf("-- FAILED %s ------------------------------------\n", f);
+ dump();
+ printf("-- FAILED %s (end) ------------------------------\n", f);
+}
+
+void run(int i, char *f) {
+ pid = fork();
+ if (pid < 0) {
+ perror("Fork failed.");
+ exit(201);
+ } else if (pid == 0) {
+ close(0);
+ dup2(fds[0], 1);
+ dup2(fds[0], 2);
+ execlp("bash", "bash", f, NULL);
+ perror("execlp");
+ fflush(stderr);
+ _exit(202);
+ } else {
+ char buf[128];
+ snprintf(buf, 128, "%s ...", f);
+ buf[127] = 0;
+ printf("Running %-40s ", buf);
+ fflush(stdout);
+ int st, w;
+ while ((w = waitpid(pid, &st, WNOHANG)) == 0) {
+ drain();
+ usleep(20000);
+ }
+ if (w != pid) {
+ perror("waitpid");
+ exit(206);
+ }
+ drain();
+ if (WIFEXITED(st)) {
+ if (WEXITSTATUS(st) == 0) {
+ passed(i, f);
+ } else if (WEXITSTATUS(st) == 200) {
+ skipped(i, f);
+ } else {
+ failed(i, f, st);
+ }
+ } else {
+ failed(i, f, st);
+ }
+ clear();
+ }
+}
+
+int main(int argc, char **argv) {
+ int i;
+
+ if (argc >= MAX) {
+ fprintf(stderr, "Sorry, my head exploded. Please increase MAX.\n");
+ exit(1);
+ }
+
+ s.nwarned = s.nfailed = s.npassed = s.nskipped = 0;
+
+ char *config = getenv("LVM_TEST_CONFIG"),
+ *config_debug,
+ *be_verbose = getenv("VERBOSE");
+ if (be_verbose && atoi(be_verbose))
+ verbose = 1; // XXX
+ config = config ? config : "";
+ asprintf(&config_debug, "%s\n%s\n", config, "log { verbose=4 }");
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) {
+ perror("socketpair");
+ return 201;
+ }
+
+ if ( fcntl( fds[1], F_SETFL, O_NONBLOCK ) == -1 ) {
+ perror("fcntl on socket");
+ return 202;
+ }
+
+ /* set up signal handlers */
+ for (i = 0; i <= 32; ++i) {
+ if (i == SIGCHLD || i == SIGWINCH || i == SIGURG)
+ continue;
+ signal(i, handler);
+ }
+
+ /* run the tests */
+ for (i = 1; i < argc; ++ i) {
+ run(i, argv[i]);
+ if (die)
+ break;
+ }
+
+ printf("\n## %d tests: %d OK, %d warnings, %d failures; %d skipped\n",
+ s.nwarned + s.npassed + s.nfailed + s.nskipped,
+ s.npassed, s.nwarned, s.nfailed, s.nskipped);
+
+ /* print out a summary */
+ if (s.nfailed || s.nskipped) {
+ for (i = 1; i < argc; ++ i) {
+ switch (s.status[i]) {
+ case FAILED:
+ printf("FAILED: %s\n", argv[i]);
+ break;
+ case SKIPPED:
+ printf("skipped: %s\n", argv[i]);
+ break;
+ }
+ }
+ printf("\n");
+ return s.nfailed > 0 || die;
+ }
+ return die;
+}
diff --git a/test/harness.sh b/test/harness.sh
new file mode 100644
index 0000000..b4bdd69
--- /dev/null
+++ b/test/harness.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+tests="$@"
+test -z "$tests" && tests=`echo t-*.sh`
+
+for t in $tests; do
+ printf "Running %-40s" "$t ..."
+ out=`bash ./$t 2>&1`
+ ret=$?
+ if test $ret = 0; then
+ echo " passed."
+ elif test $ret = 200; then
+ skipped="$skipped $t"
+ echo " skipped."
+ else
+ echo " FAILED!"
+ len=`echo $t | wc -c`
+ # fancy formatting...
+ printf -- "--- Output: $t -"
+ for i in `seq $(($len + 14)) 78`; do echo -n "-"; done; echo
+ printf "%s\n" "$out"
+ printf -- "--- End: $t ----"
+ for i in `seq $(($len + 14)) 78`; do echo -n "-"; done; echo
+ failed="$failed $t"
+ fi
+done
+
+if test -n "$failed"; then
+ echo "Tests skipped:"
+ for t in $skipped; do
+ printf "\t%s\n" $t
+ done
+ echo "TESTS FAILED:"
+ for t in $failed; do
+ printf "\t%s\n" $t
+ done
+ exit 1
+else
+ echo "All tests passed."
+fi
diff --git a/test/lvm-utils.sh b/test/lvm-utils.sh
new file mode 100644
index 0000000..fec4e2c
--- /dev/null
+++ b/test/lvm-utils.sh
@@ -0,0 +1,153 @@
+# Put lvm-related utilities here.
+# This file is sourced from test-lib.sh.
+
+# Copyright (C) 2007, 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+export LVM_SUPPRESS_FD_WARNINGS=1
+
+ME=$(basename "$0")
+warn() { echo >&2 "$ME: $@"; }
+
+trim()
+{
+ trimmed=${1%% }
+ trimmed=${trimmed## }
+
+ echo "$trimmed"
+}
+
+compare_two_fields_()
+{
+ local cmd1=$1;
+ local obj1=$2;
+ local field1=$3;
+ local cmd2=$4;
+ local obj2=$5;
+ local field2=$6;
+ local val1;
+ local val2;
+
+ val1=$($cmd1 --noheadings -o $field1 $obj1)
+ val2=$($cmd2 --noheadings -o $field2 $obj2)
+if test "$verbose" = "t"
+then
+ echo "compare_two_fields_ $obj1($field1): $val1 $obj2($field2): $val2"
+fi
+ test "$val1" = "$val2"
+}
+
+compare_vg_field_()
+{
+ local vg1=$1;
+ local vg2=$2;
+ local field=$3;
+ local val1;
+ local val2;
+
+ val1=$(vgs --noheadings -o $field $vg1)
+ val2=$(vgs --noheadings -o $field $vg2)
+if test "$verbose" = "t"
+then
+ echo "compare_vg_field_ VG1: $val1 VG2: $val2"
+fi
+ test "$val1" = "$val2"
+}
+
+
+get_pv_field() {
+ local pv=$1
+ local field=$2
+ local value
+ pvs --noheading -o $field $pv | sed 's/^ *//'
+}
+
+get_vg_field() {
+ local vg=$1
+ local field=$2
+ local value
+ vgs --noheading -o $field $vg | sed 's/^ *//'
+}
+
+get_lv_field() {
+ local lv=$1
+ local field=$2
+ local value
+ lvs --noheading -o $field $lv | sed 's/^ *//'
+}
+
+check_vg_field_()
+{
+ local vg=$1;
+ local field=$2;
+ local expected=$3;
+ local actual;
+
+ actual=$(trim $(vgs --noheadings -o $field $vg))
+if test "$verbose" = "t"
+then
+ echo "check_vg_field_ VG=$vg, field=$field, actual=$actual, expected=$expected"
+fi
+ test "$actual" = "$expected"
+}
+
+check_pv_field_()
+{
+ local pv=$1;
+ local field=$2;
+ local expected=$3;
+ local pvs_args=$4; # optional
+ local actual;
+
+ actual=$(trim $(pvs --noheadings $pvs_args -o $field $pv))
+if test "$verbose" = "t"
+then
+ echo "check_pv_field_ PV=$pv, field=$field, actual=$actual, expected=$expected"
+fi
+ test "$actual" = "$expected"
+}
+
+check_lv_field_()
+{
+ local lv=$1;
+ local field=$2;
+ local expected=$3;
+ local actual;
+
+ actual=$(trim $(lvs --noheadings -o $field $lv))
+if test "$verbose" = "t"
+then
+ echo "check_lv_field_ LV=$lv, field=$field, actual=$actual, expected=$expected"
+fi
+ test "$actual" = "$expected"
+}
+
+vg_validate_pvlv_counts_()
+{
+ local local_vg=$1
+ local num_pvs=$2
+ local num_lvs=$3
+ local num_snaps=$4
+
+ lvs -a -o+devices $local_vg
+
+ check_vg_field_ $local_vg pv_count $num_pvs && \
+ check_vg_field_ $local_vg lv_count $num_lvs && \
+ check_vg_field_ $local_vg snap_count $num_snaps
+}
+
+dmsetup_has_dm_devdir_support_()
+{
+ # Detect support for the envvar. If it's supported, the
+ # following command will fail with the expected diagnostic.
+ out=$(DM_DEV_DIR=j dmsetup version 2>&1)
+ test "$?:$out" = "1:Invalid DM_DEV_DIR envvar value." -o \
+ "$?:$out" = "1:Invalid DM_DEV_DIR environment variable value."
+}
diff --git a/test/mkdtemp b/test/mkdtemp
new file mode 100755
index 0000000..89be8ac
--- /dev/null
+++ b/test/mkdtemp
@@ -0,0 +1,120 @@
+#!/bin/sh
+# Create a temporary directory, sort of like mktemp -d does.
+
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Written by Jim Meyering.
+
+# Usage: mkdtemp /tmp phoey.XXXXXXXXXX
+
+# First, try to use the mktemp program.
+# Failing that, we'll roll our own mktemp-like function:
+# - try to get random bytes from /dev/urandom
+# - failing that, generate output from a combination of quickly-varying
+# sources and gzip. Ignore non-varying gzip header, and extract
+# "random" bits from there.
+# - given those bits, map to file-name bytes using tr, and try to create
+# the desired directory.
+# - make only $MAX_TRIES attempts
+
+ME=$(basename "$0")
+die() { echo >&2 "$ME: $@"; exit 1; }
+
+MAX_TRIES=4
+
+rand_bytes()
+{
+ n=$1
+
+ chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
+
+ dev_rand=/dev/urandom
+ if test -r "$dev_rand"; then
+ # Note: 256-length($chars) == 194; 3 copies of $chars is 186 + 8 = 194.
+ head -c$n "$dev_rand" | tr -c $chars 01234567$chars$chars$chars
+ return
+ fi
+
+ cmds='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n'
+ data=$( (eval "$cmds") 2>&1 | gzip )
+
+ n_plus_50=$(expr $n + 50)
+
+ # Ensure that $data has length at least 50+$n
+ while :; do
+ len=$(echo "$data"|wc -c)
+ test $n_plus_50 -le $len && break;
+ data=$( (echo "$data"; eval "$cmds") 2>&1 | gzip )
+ done
+
+ echo "$data" \
+ | dd bs=1 skip=50 count=$n 2>/dev/null \
+ | tr -c $chars 01234567$chars$chars$chars
+}
+
+mkdtemp()
+{
+ case $# in
+ 2);;
+ *) die "Usage: $ME DIR TEMPLATE";;
+ esac
+
+ destdir=$1
+ template=$2
+
+ case $template in
+ *XXXX) ;;
+ *) die "invalid template: $template (must have a suffix of at least 4 X's)";;
+ esac
+
+ fail=0
+
+ # First, try to use mktemp.
+ d=$(env -u TMPDIR mktemp -d -t -p "$destdir" "$template" 2>/dev/null) \
+ || fail=1
+
+ # The resulting name must be in the specified directory.
+ case $d in "$destdir"*);; *) fail=1;; esac
+
+ # It must have created the directory.
+ test -d "$d" || fail=1
+
+ # It must have 0700 permissions.
+ perms=$(ls -dgo "$d" 2>/dev/null) || fail=1
+ case $perms in drwx------*) ;; *) fail=1;; esac
+
+ test $fail = 0 && {
+ echo "$d"
+ return
+ }
+
+ # If we reach this point, we'll have to create a directory manually.
+
+ # Get a copy of the template without its suffix of X's.
+ base_template=$(echo "$template"|sed 's/XX*$//')
+
+ # Calculate how many X's we've just removed.
+ nx=$(expr length "$template" - length "$base_template")
+
+ err=
+ i=1
+ while :; do
+ X=$(rand_bytes $nx)
+ candidate_dir="$destdir/$base_template$X"
+ err=$(mkdir -m 0700 "$candidate_dir" 2>&1) \
+ && { echo "$candidate_dir"; return; }
+ test $MAX_TRIES -le $i && break;
+ i=$(expr $i + 1)
+ done
+ die "$err"
+}
+
+mkdtemp "$@"
diff --git a/test/not.c b/test/not.c
new file mode 100644
index 0000000..534a356
--- /dev/null
+++ b/test/not.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int finished(const char *cmd, int status) {
+ if (!strcmp(cmd, "not"))
+ return !status;
+ if (!strcmp(cmd, "should")) {
+ if (status)
+ fprintf(stderr, "TEST WARNING: Ignoring command failure.\n");
+ return 0;
+ }
+ return 6;
+}
+
+int main(int args, char **argv) {
+ pid_t pid;
+ int status;
+ int FAILURE = 6;
+
+ if (args < 2) {
+ fprintf(stderr, "Need args\n");
+ return FAILURE;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ fprintf(stderr, "Could not fork\n");
+ return FAILURE;
+ } else if (pid == 0) { /* child */
+ execvp(argv[1], &argv[1]);
+ /* should not be accessible */
+ return FAILURE;
+ } else { /* parent */
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status)) {
+ if (WIFSIGNALED(status))
+ fprintf(stderr,
+ "Process %d died of signal %d.\n",
+ pid, WTERMSIG(status));
+ /* did not exit correctly */
+ return FAILURE;
+ }
+
+ return finished(argv[0], WEXITSTATUS(status));
+ }
+ /* not accessible */
+ return FAILURE;
+}
diff --git a/test/t-000-basic.sh b/test/t-000-basic.sh
new file mode 100755
index 0000000..ed76a6f
--- /dev/null
+++ b/test/t-000-basic.sh
@@ -0,0 +1,30 @@
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+lvm version
+
+v=$abs_top_srcdir/lib/misc/lvm-version.h
+sed -n "/#define LVM_VERSION ./s///p" "$v" | sed "s/ .*//" > expected
+
+lvm pvmove --version|sed -n "1s/.*: *\([0-9][^ ]*\) .*/\1/p" > actual
+
+# ensure they are the same
+diff -u actual expected
+
+mknod $DM_DEV_DIR/null c 1 3 || \
+ error "Can't create nodes on filesystem"
+echo >$DM_DEV_DIR/null || \
+ error "Filesystem for tests does not allow using device nodes (check nodev)"
+
+# ensure we can create devices (uses dmsetup, etc)
+aux prepare_devs 5
+
diff --git a/test/t-activate-missing.sh b/test/t-activate-missing.sh
new file mode 100644
index 0000000..4242f21
--- /dev/null
+++ b/test/t-activate-missing.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Test activation behaviour with devices missing.
+# - snapshots and their origins are only activated together; if one fails, both
+# fail
+# - partial mirrors are not activated (but maybe they should? maybe we should
+# instead lvconvert --repair them?)
+# - linear LVs with bits missing are not activated
+
+. ./test-utils.sh
+
+prepare_vg 4
+
+lvcreate -l1 -n linear1 $vg $dev1
+lvcreate -l1 -n linear2 $vg $dev2
+lvcreate -l2 -n linear12 $vg $dev1:4 $dev2:4
+
+lvcreate -l1 -n origin1 $vg $dev1
+lvcreate -s $vg/origin1 -l1 -n s_napshot2 $dev2
+
+lvcreate -l1 -m1 -n mirror12 --mirrorlog core $vg $dev1 $dev2
+lvcreate -l1 -m1 -n mirror123 $vg $dev1 $dev2 $dev3
+
+vgchange -a n $vg
+disable_dev $dev1
+not vgchange -a y $vg
+not vgck $vg
+
+check inactive $vg linear1
+check active $vg linear2
+check inactive $vg origin1
+check inactive $vg s_napshot2
+check inactive $vg linear12
+check inactive $vg mirror12
+check inactive $vg mirror123
+
+vgchange -a n $vg
+enable_dev $dev1
+disable_dev $dev2
+not vgchange -a y $vg
+not vgck $vg
+
+check active $vg linear1
+check inactive $vg linear2
+check inactive $vg linear12
+check inactive $vg origin1
+check inactive $vg s_napshot2
+check inactive $vg mirror12
+check inactive $vg mirror123
+
+vgchange -a n $vg
+enable_dev $dev2
+disable_dev $dev3
+not vgchange -a y $vg
+not vgck $vg
+
+check active $vg origin1
+check active $vg s_napshot2
+check active $vg linear1
+check active $vg linear2
+check active $vg linear12
+check inactive $vg mirror123
+check active $vg mirror12
+
+vgchange -a n $vg
+enable_dev $dev3
+disable_dev $dev4
+vgchange -a y $vg
+not vgck $vg
+
+check active $vg origin1
+check active $vg s_napshot2
+check active $vg linear1
+check active $vg linear2
+check active $vg linear12
+check active $vg mirror12
+check active $vg mirror123
diff --git a/test/t-activate-partial.sh b/test/t-activate-partial.sh
new file mode 100644
index 0000000..b6bf9cb
--- /dev/null
+++ b/test/t-activate-partial.sh
@@ -0,0 +1,30 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 3
+
+lvcreate -m 1 -l 1 -n mirror $vg
+lvchange -a n $vg/mirror
+disable_dev $dev1
+
+not vgreduce --removemissing $vg
+not lvchange -v -a y $vg/mirror
+lvchange -v --partial -a y $vg/mirror
+not lvchange -v --refresh $vg/mirror
+lvchange -v --refresh --partial $vg/mirror
+
+# also check that vgchange works
+vgchange -a n --partial $vg
+vgchange -a y --partial $vg
+
+# check vgremove
+vgremove -f $vg
diff --git a/test/t-covercmd.sh b/test/t-covercmd.sh
new file mode 100755
index 0000000..358a93e
--- /dev/null
+++ b/test/t-covercmd.sh
@@ -0,0 +1,82 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# tests basic functionality of read-ahead and ra regressions
+#
+
+. ./test-utils.sh
+
+TEST_UUID="aaaaaa-aaaa-aaaa-aaaa-aaaa-aaaa-aaaaaa"
+
+get_lvs_()
+{
+ case $(lvs --units s --nosuffix --noheadings -o $1_read_ahead "$vg"/"$lv") in
+ *$2) true ;;
+ *) false ;;
+ esac
+}
+
+aux prepare_devs 5
+
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 0 $dev3
+pvcreate $dev4
+pvcreate --norestorefile -u $TEST_UUID --metadatacopies 0 $dev5
+vgcreate -c n $vg $devs
+lvcreate -n $lv -l 5 -i5 -I256 $vg
+
+# test *scan and *display tools
+pvscan
+vgscan
+lvscan
+lvmdiskscan
+vgdisplay --units k
+lvdisplay --units g
+for i in h b s k m g t p e H B S K M G T P E ; do
+ pvdisplay --units "$i" "$dev1"
+done
+
+# test vgexport vgimport tools
+vgchange -an $vg
+vgexport $vg
+vgimport $vg
+vgchange -ay $vg
+
+# "-persistent y --major 254 --minor 20"
+# "-persistent n"
+# test various lvm utils
+for i in dumpconfig formats segtypes; do
+ lvm "$i"
+done
+
+for i in pr "p rw" an ay "-monitor y" "-monitor n" \
+ -resync -refresh "-addtag MYTAG" "-deltag MYETAG"; do
+ lvchange -$i "$vg"/"$lv"
+done
+
+pvck "$dev1"
+vgck "$vg"
+lvrename "$vg" "$lv" "$lv-rename"
+vgcfgbackup -f "$(pwd)/backup.$$" "$vg"
+vgchange -an "$vg"
+vgcfgrestore -f "$(pwd)/backup.$$" "$vg"
+pvremove -y -ff $dev5
+not vgcfgrestore -f "$(pwd)/backup.$$" "$vg"
+pvcreate -u $TEST_UUID --restorefile "$(pwd)/backup.$$" $dev5
+vgremove -f "$vg"
+pvresize --setphysicalvolumesize 10M "$dev1"
+
+# test various errors and obsoleted tools
+not lvmchange
+not lvrename "$vg"
+not lvrename "$vg-xxx"
+not lvrename "$vg" "$vg"/"$lv-rename" "$vg"/"$lv"
diff --git a/test/t-dmeventd-restart.sh b/test/t-dmeventd-restart.sh
new file mode 100644
index 0000000..6368d77
--- /dev/null
+++ b/test/t-dmeventd-restart.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 5
+prepare_dmeventd
+
+which mkfs.ext2 || exit 200
+
+lvcreate -m 3 --ig -L 1 -n 4way $vg
+lvchange --monitor y $vg/4way
+lvcreate -m 2 --ig -L 1 -n 3way $vg
+lvchange --monitor y $vg/3way
+
+dmeventd -R -f &
+LOCAL_DMEVENTD="$!"
+
+sleep 1 # wait a bit, so we talk to the new dmeventd later
+
+lvchange --monitor y --verbose $vg/3way 2>&1 | tee lvchange.out
+grep 'already monitored' lvchange.out
+lvchange --monitor y --verbose $vg/4way 2>&1 | tee lvchange.out
+grep 'already monitored' lvchange.out
diff --git a/test/t-fsadm.sh b/test/t-fsadm.sh
new file mode 100644
index 0000000..17d2090
--- /dev/null
+++ b/test/t-fsadm.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+# Copyright (C) 2008-2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='Exercise fsadm filesystem resize'
+exit 200
+
+. ./test-utils.sh
+
+aux prepare_vg 1 100
+
+# set to "skip" to avoid testing given fs and test warning result
+# i.e. check_reiserfs=skip
+check_ext3=
+check_xfs=
+check_reiserfs=
+
+which mkfs.ext3 || check_ext3=${check_ext3:=mkfs.ext3}
+which fsck.ext3 || check_ext3=${check_ext3:=fsck.ext3}
+which mkfs.xfs || check_xfs=${check_xfs:=mkfs.xfs}
+which xfs_check || check_xfs=${check_xfs:=xfs_check}
+which mkfs.reiserfs || check_reiserfs=${check_reiserfs:=mkfs.reiserfs}
+which reiserfsck || check_reiserfs=${check_reiserfs:=reiserfsck}
+
+vg_lv="$vg/$lv1"
+dev_vg_lv="$DM_DEV_DIR/$vg_lv"
+mount_dir="$TESTDIR/mnt"
+
+test ! -d $mount_dir && mkdir $mount_dir
+
+cleanup_mounted_and_teardown()
+{
+ umount $mount_dir || true
+ teardown
+}
+
+fscheck_ext3()
+{
+ fsck.ext3 -p -F -f $dev_vg_lv
+}
+
+fscheck_xfs()
+{
+ xfs_check $dev_vg_lv
+}
+
+fscheck_reiserfs()
+{
+ reiserfsck --check -p -f $dev_vg_lv </dev/null
+}
+
+check_missing()
+{
+ eval local t=$\check_$1
+ test -z "$t" && return 0
+ test "$t" = skip && return 1
+ # trick for warning test
+ echo "TEST ""WARNING: fsadm skips $1 tests, $t tool is missing"
+ return 1
+}
+
+# Test for block sizes != 1024 (rhbz #480022)
+lvcreate -n $lv1 -L20M $vg
+trap 'aux cleanup_mounted_and_teardown' EXIT
+
+if check_missing ext3; then
+ mkfs.ext3 -b4096 -j $dev_vg_lv
+
+ fsadm --lvresize resize $vg_lv 30M
+ # Fails - not enough space for 4M fs
+ not fsadm --lvresize resize $dev_vg_lv 4M
+ lvresize -L+10M -r $vg_lv
+ lvreduce -L10M -r $vg_lv
+
+ fscheck_ext3
+ mount $dev_vg_lv $mount_dir
+ not fsadm --lvresize resize $vg_lv 9M
+ lvresize -L+20M -r -n $vg_lv
+ umount $mount_dir
+ fscheck_ext3
+
+ lvresize -f -L20M $vg_lv
+fi
+
+if check_missing xfs; then
+ mkfs.xfs -l internal,size=1000b -f $dev_vg_lv
+
+ fsadm --lvresize resize $vg_lv 30M
+ # Fails - not enough space for 4M fs
+ lvresize -L+10M -r $vg_lv
+ not lvreduce -L10M -r $vg_lv
+
+ fscheck_xfs
+ mount $dev_vg_lv $mount_dir
+ lvresize -L+10M -r -n $vg_lv
+ umount $mount_dir
+ fscheck_xfs
+
+ lvresize -f -L20M $vg_lv
+fi
+
+if check_missing reiserfs; then
+ mkfs.reiserfs -s 513 -f $dev_vg_lv
+
+ fsadm --lvresize resize $vg_lv 30M
+ lvresize -L+10M -r $vg_lv
+ fsadm --lvresize -y resize $vg_lv 10M
+
+ fscheck_reiserfs
+ mount $dev_vg_lv $mount_dir
+
+ not fsadm -y --lvresize resize $vg_lv 20M
+ umount $mount_dir
+
+ lvresize -f -L20M $vg_lv
+fi
diff --git a/test/t-inconsistent-metadata.sh b/test/t-inconsistent-metadata.sh
new file mode 100644
index 0000000..310dde5
--- /dev/null
+++ b/test/t-inconsistent-metadata.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 3
+
+lvcreate -m 1 -l 1 -n mirror $vg
+lvcreate -l 1 -n resized $vg
+lvchange -a n $vg/mirror
+
+backup_dev $devs
+
+init() {
+ restore_dev $devs
+ lvs -o lv_name,lv_size --units k $vg | tee lvs.out
+ grep resized lvs.out | not grep 8192
+ lvresize -L 8192K $vg/resized
+ restore_dev $dev1
+}
+
+check() {
+ lvs -o lv_name,lv_size --units k $vg | tee lvs.out
+ grep resized lvs.out | grep 8192
+}
+
+# vgscan fixes up metadata
+init
+vgscan 2>&1 | tee cmd.out
+grep "Inconsistent metadata found for VG $vg" cmd.out
+vgscan 2>&1 | tee cmd.out
+not grep "Inconsistent metadata found for VG $vg" cmd.out
+check
+
+# vgdisplay fixes
+init
+vgdisplay 2>&1 | tee cmd.out
+grep "Inconsistent metadata found for VG $vg" cmd.out
+vgdisplay 2>&1 | tee cmd.out
+not grep "Inconsistent metadata found for VG $vg" cmd.out
+check
+
+# lvs fixes up
+init
+lvs 2>&1 | tee cmd.out
+grep "Inconsistent metadata found for VG $vg" cmd.out
+vgdisplay 2>&1 | tee cmd.out
+not grep "Inconsistent metadata found for VG $vg" cmd.out
+check
+
+# vgs fixes up as well
+init
+vgs 2>&1 | tee cmd.out
+grep "Inconsistent metadata found for VG $vg" cmd.out
+vgs 2>&1 | tee cmd.out
+not grep "Inconsistent metadata found for VG $vg" cmd.out
+check
+
+echo Check auto-repair of failed vgextend - metadata written to original pv but not new pv
+vgremove -f $vg
+pvremove -ff $devs
+pvcreate $devs
+backup_dev $dev2
+vgcreate $vg $dev1
+vgextend $vg $dev2
+restore_dev $dev2
+should compare_two_fields_ vgs $vg vg_mda_count pvs $dev2 vg_mda_count
diff --git a/test/t-listings.sh b/test/t-listings.sh
new file mode 100644
index 0000000..9ea10b6
--- /dev/null
+++ b/test/t-listings.sh
@@ -0,0 +1,83 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# tests functionality of lvs, pvs, vgs, *display tools
+#
+
+. ./test-utils.sh
+
+get_lvs_()
+{
+ case $(lvs --units s --nosuffix --noheadings -o $1_read_ahead "$vg"/"$lv") in
+ *$2) true ;;
+ *) false ;;
+ esac
+}
+
+aux prepare_devs 5
+
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 0 $dev3
+pvcreate $dev4
+pvcreate --metadatacopies 0 $dev5
+
+#COMM bz195276 -- pvs doesn't show PVs until a VG is created
+pvs --noheadings|tee out
+test $(wc -l <out) -eq 5
+
+#COMM pvs with segment attributes works even for orphans
+pvs --noheadings -o seg_all,pv_all,lv_all,vg_all | tee out
+test $(wc -l <out) -eq 5
+
+vgcreate -c n $vg $devs
+
+#COMM pvs and vgs report mda_count, mda_free (bz202886, bz247444)
+pvs -o +pv_mda_count,pv_mda_free $devs
+for I in $dev2 $dev3 $dev5; do
+ aux check_pv_field_ $I pv_mda_count 0
+ aux check_pv_field_ $I pv_mda_free 0
+done
+vgs -o +vg_mda_count,vg_mda_free $vg
+aux check_vg_field_ $vg vg_mda_count 2
+
+#COMM pvs doesn't display --metadatacopies 0 PVs as orphans (bz409061)
+pvdisplay $dev2|grep "VG Name.*$vg"
+test $(pvs -o vg_name --noheadings $dev2) = $vg
+
+#COMM lvs displays snapshots (bz171215)
+lvcreate -l4 -n $lv1 $vg
+lvcreate -l4 -s -n $lv2 $vg/$lv1
+lvs $vg --noheadings|tee out
+test $(wc -l <out) -eq 2
+lvs -a --noheadings|tee out
+# should lvs -a display cow && real devices? (it doesn't)
+test $(wc -l <out) -eq 2
+dmsetup ls|grep $PREFIX|grep -v "LVMTEST.*pv."
+lvremove -f $vg/$lv2
+
+#COMM lvs -a displays mirror legs and log
+lvcreate -l4 -m2 -n$lv3 $vg
+lvs $vg --noheadings|tee out
+test $(wc -l <out) -eq 2
+lvs -a --noheadings|tee out
+test $(wc -l <out) -eq 6
+dmsetup ls|grep $PREFIX|grep -v "LVMTEST.*pv."
+
+#COMM vgs with options from pvs still treats arguments as VGs (bz193543)
+vgs -o pv_name,vg_name $vg
+# would complain if not
+
+#COMM pvdisplay --maps feature (bz149814)
+pvdisplay $devs >out
+pvdisplay --maps $devs >out2
+not diff out out2
+
diff --git a/test/t-lock-blocking.sh b/test/t-lock-blocking.sh
new file mode 100644
index 0000000..166340c
--- /dev/null
+++ b/test/t-lock-blocking.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='test some blocking / non-blocking multi-vg operations'
+
+. ./test-utils.sh
+
+aux prepare_devs 3
+test -n "$LOCAL_CLVMD" && exit 200
+pvcreate $dev1 $dev2
+vgcreate $vg $dev1 $dev2
+
+# if wait_for_locks set, vgremove should wait for orphan lock
+# flock process should have exited by the time first vgremove completes
+flock -w 5 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 10" &
+flock_pid=`jobs -p`
+vgremove --config 'global { wait_for_locks = 1 }' $vg
+not vgremove --config 'global { wait_for_locks = 1 }' $vg
+not ps $flock_pid # finished
+
+# if wait_for_locks not set, vgremove should fail on non-blocking lock
+# we must wait for flock process at the end - vgremove won't wait
+vgcreate $vg $dev1 $dev2
+flock -w 5 $TESTDIR/var/lock/lvm/P_orphans -c "sleep 10" &
+flock_pid=`jobs -p`
+not vgremove --config 'global { wait_for_locks = 0 }' $vg
+ps $flock_pid # still running
+kill $flock_pid
diff --git a/test/t-lvchange-mirror.sh b/test/t-lvchange-mirror.sh
new file mode 100644
index 0000000..7c915be
--- /dev/null
+++ b/test/t-lvchange-mirror.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+aux prepare_vg 3
+
+# force resync 2-way active mirror
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check mirror $vg $lv1 $dev3
+echo y | lvchange --resync $vg/$lv1
+check mirror $vg $lv1 $dev3
+lvremove -ff $vg
+
+# force resync 2-way inactive mirror
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvchange -an $vg/$lv1
+check mirror $vg $lv1 $dev3
+lvchange --resync $vg/$lv1
+check mirror $vg $lv1 $dev3
+lvremove -ff $vg
diff --git a/test/t-lvconvert-mirror-basic-0.sh b/test/t-lvconvert-mirror-basic-0.sh
new file mode 100644
index 0000000..eec6d5c
--- /dev/null
+++ b/test/t-lvconvert-mirror-basic-0.sh
@@ -0,0 +1,12 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./t-lvconvert-mirror-basic.sh
+test_many 0
diff --git a/test/t-lvconvert-mirror-basic-1.sh b/test/t-lvconvert-mirror-basic-1.sh
new file mode 100644
index 0000000..7019dbb
--- /dev/null
+++ b/test/t-lvconvert-mirror-basic-1.sh
@@ -0,0 +1,12 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./t-lvconvert-mirror-basic.sh
+test_many 1
diff --git a/test/t-lvconvert-mirror-basic-2.sh b/test/t-lvconvert-mirror-basic-2.sh
new file mode 100644
index 0000000..85d54c9
--- /dev/null
+++ b/test/t-lvconvert-mirror-basic-2.sh
@@ -0,0 +1,12 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./t-lvconvert-mirror-basic.sh
+test_many 2
diff --git a/test/t-lvconvert-mirror-basic-3.sh b/test/t-lvconvert-mirror-basic-3.sh
new file mode 100644
index 0000000..0c57580
--- /dev/null
+++ b/test/t-lvconvert-mirror-basic-3.sh
@@ -0,0 +1,12 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./t-lvconvert-mirror-basic.sh
+test_many 3
diff --git a/test/t-lvconvert-mirror-basic.sh b/test/t-lvconvert-mirror-basic.sh
new file mode 100644
index 0000000..880bd09
--- /dev/null
+++ b/test/t-lvconvert-mirror-basic.sh
@@ -0,0 +1,148 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+log_name_to_count()
+{
+ if [ "$1" = "mirrored" ]; then
+ echo 2
+ elif [ "$1" = "disk" ]; then
+ echo 1
+ else
+ echo 0
+ fi
+}
+
+# FIXME: For test_[up|down]convert, I'd still like to be able
+# to specifiy devices - especially if I can do partial PV
+# specification for down-converts. It may even be wise to
+# do one round through these tests without specifying the PVs
+# to use and one round where we do.
+
+# test_lvconvert
+# start_mirror_count: The '-m' argument to create with
+# start_log_type: core|disk|mirrored
+# final_mirror_count: The '-m' argument to convert to
+# final_log_type: core|disk|mirrored
+# active: Whether the LV should be active when the convert happens
+#
+# Exmaple: Convert 3-way disk-log mirror to
+# 2-way disk-log mirror while not active
+# -> test_lvconvert 2 disk 3 disk 0
+
+test_lvconvert()
+{
+ local start_count=$1
+ local start_count_p1=$(($start_count + 1))
+ local start_log_type=$2
+ local finish_count=$3
+ local finish_count_p1=$(($finish_count + 1))
+ local finish_log_type=$4
+ local dev_array=($dev1 $dev2 $dev3 $dev4 $dev5)
+ local start_log_count
+ local finish_log_count
+ local max_log_count
+ local alloc=""
+ local active=true
+ local i
+
+ if [ "$start_log_type" = "disk" ] &&
+ [ "$finish_log_type" = "mirrored" ]; then
+ echo "FIXME: disk -> mirrored log conversion not yet supported by LVM"
+ return 0
+ fi
+
+ test "$5" = "active" && active=false
+ #test $finish_count -gt $start_count && up=true
+
+ # Do we have enough devices for the mirror images?
+ if [ $start_count_p1 -gt ${#dev_array[@]} ]; then
+ echo "Action requires too many devices"
+ return 1
+ fi
+
+ # Do we have enough devices for the mirror images?
+ if [ $finish_count_p1 -gt ${#dev_array[@]} ]; then
+ echo "Action requires too many devices"
+ return 1
+ fi
+
+ start_log_count=`log_name_to_count $start_log_type`
+ finish_log_count=`log_name_to_count $finish_log_type`
+ if [ $finish_log_count -gt $start_log_count ]; then
+ max_log_count=$finish_log_count
+ else
+ max_log_count=$start_log_count
+ fi
+
+ prepare_vg 5
+
+ if [ $start_count -gt 0 ]; then
+ # Are there extra devices for the log or do we overlap
+ if [ $(($start_count_p1 + $start_log_count)) -gt ${#dev_array[@]} ]; then
+ alloc="--alloc anywhere"
+ fi
+
+ lvcreate -l2 -m $start_count --mirrorlog $start_log_type \
+ -n $lv1 $vg $alloc
+ check mirror_legs $vg $lv1 $start_count_p1
+ # FIXME: check mirror log
+ else
+ lvcreate -l2 -n $lv1 $vg
+ fi
+
+ lvs -a -o name,copy_percent,devices $vg
+ if ! $active; then
+ lvchange -an $vg/$lv1
+ fi
+
+ # Are there extra devices for the log or do we overlap
+ if [ $(($finish_count_p1 + $finish_log_count)) -gt ${#dev_array[@]} ]; then
+ alloc="--alloc anywhere"
+ fi
+
+ echo y | lvconvert -m $finish_count --mirrorlog $finish_log_type \
+ $vg/$lv1 $alloc
+
+ if ! $active; then
+ lvchange -ay $vg/$lv1
+ fi
+
+ check mirror_no_temporaries $vg $lv1
+ if [ "$finish_count_p1" -eq 1 ]; then
+ check linear $vg $lv1
+ else
+ if test -n "$alloc"; then
+ check mirror_nonredundant $vg $lv1
+ else
+ check mirror $vg $lv1
+ fi
+ check mirror_legs $vg $lv1 $finish_count_p1
+ fi
+}
+
+aux prepare_vg 5
+
+test_many() {
+ i=$1
+ for j in $(seq 0 3); do
+ for k in core disk mirrored; do
+ for l in core disk mirrored; do
+ if test "$i" -eq "$j" && test "$k" = "$l"; then continue; fi
+ : ----------------------------------------------------
+ : "Testing mirror conversion -m$i/$k -> -m$j/$l"
+ : ----------------------------------------------------
+ test_lvconvert $i $k $j $l 0
+ test_lvconvert $i $k $j $l 1
+ done
+ done
+ done
+}
diff --git a/test/t-lvconvert-mirror.sh b/test/t-lvconvert-mirror.sh
new file mode 100644
index 0000000..c33196c
--- /dev/null
+++ b/test/t-lvconvert-mirror.sh
@@ -0,0 +1,242 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+# convert from linear to 2-way mirror
+aux prepare_vg 5
+lvcreate -l2 -n $lv1 $vg $dev1
+lvconvert -i1 -m+1 $vg/$lv1 $dev2 $dev3:0-1
+check mirror $vg $lv1 $dev3
+
+# convert from 2-way mirror to linear
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvconvert -m-1 $vg/$lv1
+check linear $vg $lv1
+lvremove -ff $vg
+# and now try removing a specific leg (bz453643)
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvconvert -m0 $vg/$lv1 $dev2
+check lv_on $vg $lv1 $dev1
+lvremove -ff $vg
+
+# convert from disklog to corelog, active
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvconvert -f --mirrorlog core $vg/$lv1
+check mirror $vg $lv1 core
+lvremove -ff $vg
+
+# convert from corelog to disklog, active
+aux prepare_vg 5
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+lvconvert --mirrorlog disk $vg/$lv1 $dev3:0-1
+check mirror $vg $lv1 $dev3
+lvremove -ff $vg
+
+# bz192865: lvconvert log of an inactive mirror lv
+# convert from disklog to corelog, inactive
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvchange -an $vg/$lv1
+echo y | lvconvert -f --mirrorlog core $vg/$lv1
+check mirror $vg $lv1 core
+lvremove -ff $vg
+
+# convert from corelog to disklog, inactive
+aux prepare_vg 5
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+lvchange -an $vg/$lv1
+lvconvert --mirrorlog disk $vg/$lv1 $dev3:0-1
+check mirror $vg $lv1 $dev3
+lvremove -ff $vg
+
+# convert linear to 2-way mirror with 1 PV
+aux prepare_vg 5
+lvcreate -l2 -n $lv1 $vg $dev1
+not lvconvert -m+1 --mirrorlog core $vg/$lv1 $dev1
+lvremove -ff $vg
+
+# Start w/ 3-way mirror
+# Test pulling primary image before mirror in-sync (should fail)
+# Test pulling primary image after mirror in-sync (should work)
+# Test that the correct devices remain in the mirror
+lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev4 $dev3:0
+# FIXME:
+# This is somewhat timing dependent - sync /could/ finish before
+# we get a chance to have this command fail
+should not lvconvert -m-1 $vg/$lv1 $dev1
+
+lvconvert $vg/$lv1 # wait
+lvconvert -m2 $vg/$lv1 $dev1 $dev2 $dev4 $dev3:0 # If the above "should" failed...
+
+lvconvert -m-1 $vg/$lv1 $dev1
+check mirror_images_on $lv1 $dev2 $dev4
+lvconvert -m-1 $vg/$lv1 $dev2
+check linear $vg $lv1
+check lv_on $vg $lv1 $dev4
+
+# No parallel lvconverts on a single LV please
+
+aux prepare_vg 5
+lvcreate -l5 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+check mirror $vg $lv1
+check mirror_legs $vg $lv1 2
+lvconvert -m+1 -b $vg/$lv1 $dev4
+
+# Next convert should fail b/c we can't have 2 at once
+should not lvconvert -m+1 $vg/$lv1 $dev5
+lvconvert $vg/$lv1 # wait
+lvconvert -m2 $vg/$lv1 # In case the above "should" actually failed
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 3
+
+# add 1 mirror to core log mirror, but
+# implicitly keep log as 'core'
+aux prepare_vg 5
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+lvconvert -m +1 -i1 $vg/$lv1
+
+check mirror $vg $lv1 core
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 3
+
+# remove 1 mirror from corelog'ed mirror; should retain 'core' log type
+aux prepare_vg 5
+lvcreate -l2 -m2 --corelog -n $lv1 $vg
+lvconvert -m -1 -i1 $vg/$lv1
+
+check mirror $vg $lv1 core
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 2
+
+# add 1 mirror then add 1 more mirror during conversion
+# FIXME this has been explicitly forbidden?
+#aux prepare_vg 5
+#lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+#lvconvert -m+1 -b $vg/$lv1 $dev4
+#lvconvert -m+1 $vg/$lv1 $dev5
+#
+#check mirror $vg $lv1 $dev3
+#check mirror_no_temporaries $vg $lv1
+#check mirror_legs $vg $lv1 4
+
+# Linear to mirror with mirrored log using --alloc anywhere
+aux prepare_vg 5
+lvcreate -l2 -n $lv1 $vg $dev1
+lvconvert -m +1 --mirrorlog mirrored $vg/$lv1 $dev1 $dev2 --alloc anywhere
+should check mirror $vg $lv1
+
+# convert inactive mirror and start polling
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+lvchange -an $vg/$lv1
+lvconvert -m+1 $vg/$lv1 $dev4
+lvchange -ay $vg/$lv1
+lvconvert $vg/$lv1 # wait
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+
+# ---------------------------------------------------------------------
+# removal during conversion
+
+# "remove newly added mirror"
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+lvconvert -m+1 -b $vg/$lv1 $dev4
+lvconvert -m-1 $vg/$lv1 $dev4
+lvconvert $vg/$lv1 # wait
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 2
+
+# "remove one of newly added mirrors"
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+lvconvert -m+2 -b $vg/$lv1 $dev4 $dev5
+lvconvert -m-1 $vg/$lv1 $dev4
+lvconvert $vg/$lv1 # wait
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 3
+
+# "remove from original mirror (the original is still mirror)"
+aux prepare_vg 5
+lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev5 $dev3:0
+lvconvert -m+1 -b $vg/$lv1 $dev4
+lvconvert -m-1 $vg/$lv1 $dev2
+lvconvert $vg/$lv1
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 3
+
+# "remove from original mirror (the original becomes linear)"
+aux prepare_vg 5
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+lvconvert -m+1 -b $vg/$lv1 $dev4
+lvconvert -m-1 $vg/$lv1 $dev2
+lvconvert $vg/$lv1
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 2
+
+# ---------------------------------------------------------------------
+
+# "rhbz440405: lvconvert -m0 incorrectly fails if all PEs allocated"
+aux prepare_vg 5
+lvcreate -l`pvs --noheadings -ope_count $dev1` -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+while [ `lvs --noheadings -o copy_percent $vg/$lv1` != "100.00" ]; do sleep 1; done
+lvconvert -m0 $vg/$lv1 $dev1
+check linear $vg $lv1
+
+# "rhbz264241: lvm mirror doesn't lose it's "M" --nosync attribute after being down and the up converted"
+aux prepare_vg 5
+lvcreate -l2 -m1 -n$lv1 --nosync $vg
+lvconvert -m0 $vg/$lv1
+lvconvert -m1 $vg/$lv1
+lvs --noheadings -o attr $vg/$lv1 | grep '^ *m'
+
+# lvconvert from linear (on multiple PVs) to mirror
+aux prepare_vg 5
+lvcreate -l 8 -n $lv1 $vg $dev1:0-3 $dev2:0-3
+lvconvert -m1 $vg/$lv1
+
+should check mirror $vg $lv1
+check mirror_legs $vg $lv1 2
+
+# BZ 463272: disk log mirror convert option is lost if downconvert option is also given
+aux prepare_vg 5
+lvcreate -l1 -m2 --corelog -n $lv1 $vg $dev1 $dev2 $dev3
+while [ `lvs --noheadings -o copy_percent $vg/$lv1` != "100.00" ]; do sleep 1; done
+lvconvert -m1 --mirrorlog disk $vg/$lv1
+check mirror $vg $lv1
+not check mirror $vg $lv1 core
+
+# ---
+# add mirror and disk log
+
+# "add 1 mirror and disk log"
+aux prepare_vg 5
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+
+# FIXME on next line, specifying $dev3:0 $dev4 (i.e log device first) fails (!)
+lvconvert -m+1 --mirrorlog disk -i1 $vg/$lv1 $dev4 $dev3:0
+
+check mirror $vg $lv1 $dev3
+check mirror_no_temporaries $vg $lv1
+check mirror_legs $vg $lv1 3
diff --git a/test/t-lvconvert-repair-dmeventd.sh b/test/t-lvconvert-repair-dmeventd.sh
new file mode 100644
index 0000000..f80a410
--- /dev/null
+++ b/test/t-lvconvert-repair-dmeventd.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 5
+prepare_dmeventd
+
+which mkfs.ext2 || exit 200
+
+lvcreate -m 3 --ig -L 1 -n 4way $vg
+lvchange --monitor y $vg/4way
+disable_dev $dev2 $dev4
+mkfs.ext2 $DM_DEV_DIR/$vg/4way
+sleep 10 # FIXME: need a "poll" utility, akin to "check"
+enable_dev $dev2 $dev4
+check mirror $vg 4way
+check mirror_legs $vg 4way 2
diff --git a/test/t-lvconvert-repair-policy.sh b/test/t-lvconvert-repair-policy.sh
new file mode 100644
index 0000000..1f31215
--- /dev/null
+++ b/test/t-lvconvert-repair-policy.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 4
+
+# Clean-up and create a 2-way mirror, where the the
+# leg devices are always on $dev[12] and the log
+# is always on $dev3. ($dev4 behaves as a spare)
+cleanup() {
+ vgreduce --removemissing $vg
+ for d in "$@"; do enable_dev $d; done
+ for d in "$@"; do vgextend $vg $d; done
+ lvremove -ff $vg/mirror
+ lvcreate -m 1 --ig -l 2 -n mirror $vg $dev1 $dev2 $dev3:0
+}
+
+repair() {
+ lvconvert --repair --use-policies --config "$1" $vg/mirror
+}
+
+lvcreate -m 1 -L 1 -n mirror $vg
+lvchange -a n $vg/mirror
+
+# Fail a leg of a mirror.
+aux disable_dev $dev1
+lvchange --partial -a y $vg/mirror
+repair 'activation { mirror_image_fault_policy = "remove" }'
+check linear $vg mirror
+aux cleanup $dev1
+
+# Fail a leg of a mirror.
+# Expected result: Mirror (leg replaced)
+aux disable_dev $dev1
+repair 'activation { mirror_image_fault_policy = "replace" }'
+check mirror $vg mirror
+lvs | grep mirror_mlog
+aux cleanup $dev1
+
+# Fail a leg of a mirror (use old name for policy specification)
+# Expected result: Mirror (leg replaced)
+aux disable_dev $dev1
+repair 'activation { mirror_device_fault_policy = "replace" }'
+check mirror $vg mirror
+lvs | grep mirror_mlog
+aux cleanup $dev1
+
+# Fail a leg of a mirror w/ no available spare
+# Expected result: 2-way with corelog
+aux disable_dev $dev2 $dev4
+repair 'activation { mirror_image_fault_policy = "replace" }'
+check mirror $vg mirror
+lvs | not grep mirror_mlog
+aux cleanup $dev2 $dev4
+
+# Fail the log device of a mirror w/ no available spare
+# Expected result: mirror w/ corelog
+aux disable_dev $dev3 $dev4
+repair 'activation { mirror_image_fault_policy = "replace" }' $vg/mirror
+check mirror $vg mirror
+lvs | not grep mirror_mlog
+aux cleanup $dev3 $dev4
+
+# Fail the log device with a remove policy
+# Expected result: mirror w/ corelog
+lvchange -a y $vg/mirror
+aux disable_dev $dev3 $dev4
+repair 'activation { mirror_log_fault_policy = "remove" }'
+check mirror $vg mirror core
+lvs | not grep mirror_mlog
+cleanup $dev3 $dev4
diff --git a/test/t-lvconvert-repair-replace.sh b/test/t-lvconvert-repair-replace.sh
new file mode 100644
index 0000000..7315a0e
--- /dev/null
+++ b/test/t-lvconvert-repair-replace.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 6
+
+# multiple failures, full replace
+lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4:0-1
+disable_dev $dev1 $dev2
+echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out
+lvs -a -o +devices | not grep unknown
+not grep "WARNING: Failed" 3way.out
+vgreduce --removemissing $vg
+check mirror $vg 3way
+enable_dev $dev1 $dev2
+
+vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4 $dev5
+
+# multiple failures, partial replace
+lvcreate --mirrorlog disk -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4
+disable_dev $dev1 $dev2
+echo y | lvconvert --repair $vg/3way 2>&1 | tee 3way.out
+grep "WARNING: Failed" 3way.out
+lvs -a -o +devices | not grep unknown
+vgreduce --removemissing $vg
+check mirror $vg 3way
+enable_dev $dev1 $dev2
+lvchange -a n $vg/3way
+
+vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3
+
+lvcreate --mirrorlog disk -m 1 --ig -L 1 -n 2way $vg $dev1 $dev2 $dev3
+disable_dev $dev1
+echo y | lvconvert --repair $vg/2way 2>&1 | tee 2way.out
+grep "WARNING: Failed" 2way.out
+lvs -a -o +devices | not grep unknown
+vgreduce --removemissing $vg
+check mirror $vg 2way
+enable_dev $dev1 $dev2
+lvchange -a n $vg/2way
+
+vgremove -ff $vg; vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4
+
+# Test repair of inactive mirror with log failure
+# Replacement should fail, but covert should succeed (switch to corelog)
+lvcreate -m 2 --ig -l 2 -n mirror2 $vg $dev1 $dev2 $dev3 $dev4:0
+vgchange -a n $vg
+pvremove -ff -y $dev4
+echo 'y' | lvconvert -y --repair $vg/mirror2
+check mirror $vg mirror2
+vgs
+
diff --git a/test/t-lvconvert-repair-transient.sh b/test/t-lvconvert-repair-transient.sh
new file mode 100644
index 0000000..b4e1a06
--- /dev/null
+++ b/test/t-lvconvert-repair-transient.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 5
+
+exit 200 # this breaks upstream .33 and RHEL6 kernel :(
+
+# fail multiple devices
+
+lvcreate -m 3 --ig -L 1 -n 4way $vg
+disable_dev $dev2 $dev4
+mkfs.ext3 $DM_DEV_DIR/$vg/4way
+enable_dev $dev2 $dev4
+echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out
+lvs -a -o +devices | not grep unknown
+vgreduce --removemissing $vg
+check mirror $vg 4way
+lvchange -a n $vg/4way
diff --git a/test/t-lvconvert-repair.sh b/test/t-lvconvert-repair.sh
new file mode 100644
index 0000000..bce8b53
--- /dev/null
+++ b/test/t-lvconvert-repair.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+
+# fail multiple devices
+
+aux prepare_vg 5
+lvcreate -m 3 --ig -L 1 -n 4way $vg $dev1 $dev2 $dev3 $dev4 $dev5:0
+disable_dev $dev2 $dev4
+echo n | lvconvert --repair $vg/4way 2>&1 | tee 4way.out
+lvs -a -o +devices | not grep unknown
+vgreduce --removemissing $vg
+enable_dev $dev2 $dev4
+check mirror $vg 4way $dev5
+
+aux prepare_vg 5
+lvcreate -m 2 --ig -L 1 -n 3way $vg
+disable_dev $dev1 $dev2
+echo n | lvconvert --repair $vg/3way
+check linear $vg 3way
+lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+dmsetup ls | grep $PREFIX | not grep mlog
+vgreduce --removemissing $vg
+enable_dev $dev1 $dev2
+check linear $vg 3way
+
+# fail just log and get it removed
+
+aux prepare_vg 5
+lvcreate -m 2 --ig -L 1 -n 3way $vg $dev1 $dev2 $dev3 $dev4:0
+disable_dev $dev4
+echo n | lvconvert --repair $vg/3way
+check mirror $vg 3way core
+lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+dmsetup ls | grep $PREFIX | not grep mlog
+vgreduce --removemissing $vg
+enable_dev $dev4
+
+aux prepare_vg 5
+lvcreate -m 1 --ig -L 1 -n 2way $vg $dev1 $dev2 $dev3:0
+disable_dev $dev3
+echo n | lvconvert --repair $vg/2way
+check mirror $vg 2way core
+lvs -a -o +devices | not grep unknown
+lvs -a -o +devices | not grep mlog
+vgreduce --removemissing $vg
+enable_dev $dev3
+
+# fail single devices
+
+aux prepare_vg 5
+vgreduce $vg $dev4
+
+lvcreate -m 1 --ig -L 1 -n mirror $vg
+lvchange -a n $vg/mirror
+vgextend $vg $dev4
+disable_dev $dev1
+lvchange --partial -a y $vg/mirror
+
+not vgreduce -v --removemissing $vg
+lvconvert -y --repair $vg/mirror
+vgreduce --removemissing $vg
+
+enable_dev $dev1
+vgextend $vg $dev1
+disable_dev $dev2
+lvconvert -y --repair $vg/mirror
+vgreduce --removemissing $vg
+
+enable_dev $dev2
+vgextend $vg $dev2
+disable_dev $dev3
+lvconvert -y --repair $vg/mirror
+vgreduce --removemissing $vg
+enable_dev $dev3
+vgextend $vg $dev3
+lvremove -ff $vg
diff --git a/test/t-lvconvert-twostep.sh b/test/t-lvconvert-twostep.sh
new file mode 100644
index 0000000..c499fdd
--- /dev/null
+++ b/test/t-lvconvert-twostep.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 4
+lvcreate -m 1 --mirrorlog disk --ig -L 1 -n mirror $vg
+not lvconvert -m 2 --mirrorlog core $vg/mirror $dev3 2>&1 | tee errs
+grep "two steps" errs
+lvconvert -m 2 $vg/mirror $dev3
+lvconvert --mirrorlog core $vg/mirror
+not lvconvert -m 1 --mirrorlog disk $vg/mirror $dev3 2>&1 | tee errs
+grep "two steps" errs
diff --git a/test/t-lvcreate-mirror.sh b/test/t-lvcreate-mirror.sh
new file mode 100644
index 0000000..ae3fceb
--- /dev/null
+++ b/test/t-lvcreate-mirror.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+aux prepare_vg 5 80
+
+# 2-way mirror with corelog, 2 PVs
+lvcreate -l2 -m1 --mirrorlog core -n $lv1 $vg $dev1 $dev2
+check mirror_images_redundant $vg $lv1
+lvremove -ff $vg
+
+# 2-way mirror with disklog, 3 PVs
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+check mirror_images_redundant $vg $lv1
+check mirror_log_on $vg $lv1 $dev3
+lvremove -ff $vg
+
+# 3-way mirror with disklog, 4 PVs
+lvcreate -l2 -m2 --mirrorlog disk -n $lv1 $vg $dev1 $dev2 $dev4 $dev3:0-1
+check mirror_images_redundant $vg $lv1
+check mirror_log_on $vg $lv1 $dev3
+lvremove -ff $vg
+
+# lvcreate --nosync is in 100% sync after creation (bz429342)
+lvcreate -l2 -m1 --nosync -n $lv1 $vg $dev1 $dev2 $dev3:0-1 2>out
+grep "New mirror won't be synchronised." out
+lvs -o copy_percent --noheadings $vg/$lv1 | grep 100.00
+lvremove -ff $vg
+
+# creating 2-way mirror with disklog from 2 PVs fails
+not lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2
diff --git a/test/t-lvcreate-operation.sh b/test/t-lvcreate-operation.sh
new file mode 100644
index 0000000..8a31759
--- /dev/null
+++ b/test/t-lvcreate-operation.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Exercise some lvcreate diagnostics'
+
+. ./test-utils.sh
+
+cleanup_lvs() {
+ lvremove -ff $vg
+ if dmsetup table|grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!"
+ return 1
+ fi
+}
+
+prepare_pvs 2
+aux pvcreate --metadatacopies 0 $dev1
+aux vgcreate -c n $vg $devs
+
+# ---
+# Create snapshots of LVs on --metadatacopies 0 PV (bz450651)
+lvcreate -n$lv1 -l4 $vg $dev1
+lvcreate -n$lv2 -l4 -s $vg/$lv1
+cleanup_lvs
+
+# ---
+# Create mirror on two devices with mirrored log using --alloc anywhere
+lvcreate -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere $dev1 $dev2
+cleanup_lvs
+
+# --
+# Create mirror on one dev with mirrored log using --alloc anywhere, should fail
+not lvcreate -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere $dev1
+cleanup_lvs
diff --git a/test/t-lvcreate-pvtags.sh b/test/t-lvcreate-pvtags.sh
new file mode 100755
index 0000000..b9a4380
--- /dev/null
+++ b/test/t-lvcreate-pvtags.sh
@@ -0,0 +1,42 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 3
+# not required, just testing
+aux pvcreate --metadatacopies 0 $dev1
+
+vgcreate -c n $vg $devs
+pvchange --addtag fast $devs
+
+# 3 stripes with 3 PVs (selected by tag, @fast) is fine
+lvcreate -l3 -i3 $vg @fast
+
+# too many stripes(4) for 3 PVs
+not lvcreate -l4 -i4 $vg @fast
+
+# 2 stripes is too many with just one PV
+not lvcreate -l2 -i2 $vg $DM_DEV_DIR/mapper/pv1
+
+# lvcreate mirror
+lvcreate -l1 -m1 $vg @fast
+
+# lvcreate mirror w/corelog
+lvcreate -l1 -m2 --corelog $vg @fast
+
+# lvcreate mirror w/no free PVs
+not lvcreate -l1 -m2 $vg @fast
+
+# lvcreate mirror (corelog, w/no free PVs)
+not lvcreate -l1 -m3 --corelog $vg @fast
+
+# lvcreate mirror with a single PV arg
+not lvcreate -l1 -m1 --corelog $vg $dev1
diff --git a/test/t-lvcreate-small-snap.sh b/test/t-lvcreate-small-snap.sh
new file mode 100644
index 0000000..789c099
--- /dev/null
+++ b/test/t-lvcreate-small-snap.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 3
+
+vgcreate -c n -s 1k $vg $devs
+
+lvcreate -n one -l 10 $vg
+lvcreate -s -l 8 -n snapA $vg/one
+lvcreate -s -c 4k -l 8 -n snapX1 $vg/one
+lvcreate -s -c 8k -l 16 -n snapX2 $vg/one
+
+# Check that snapshots that are too small are caught with correct error.
+not lvcreate -s -c 8k -l 8 -n snapX3 $vg/one 2>&1 | tee lvcreate.out
+not grep "suspend origin one" lvcreate.out
+grep "Unable to create a snapshot" lvcreate.out
+
+not lvcreate -s -l 4 -n snapB $vg/one 2>&1 | tee lvcreate.out
+not grep "suspend origin one" lvcreate.out
+grep "Unable to create a snapshot" lvcreate.out
diff --git a/test/t-lvcreate-usage.sh b/test/t-lvcreate-usage.sh
new file mode 100755
index 0000000..0bb06ab
--- /dev/null
+++ b/test/t-lvcreate-usage.sh
@@ -0,0 +1,141 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Exercise some lvcreate diagnostics'
+
+. ./test-utils.sh
+
+aux prepare_pvs 4
+aux pvcreate --metadatacopies 0 $dev1
+vgcreate -cn $vg $devs
+
+# "lvcreate rejects repeated invocation (run 2 times) (bz178216)"
+lvcreate -n $lv -l 4 $vg
+not lvcreate -n $lv -l 4 $vg
+lvremove -ff $vg/$lv
+# try to remove it again - should fail (but not segfault)
+not lvremove -ff $vg/$lv
+
+# "lvcreate rejects a negative stripe_size"
+not lvcreate -L 64m -n $lv -i2 --stripesize -4 $vg 2>err;
+grep "^ Negative stripesize is invalid\$" err
+
+# 'lvcreate rejects a too-large stripesize'
+not lvcreate -L 64m -n $lv -i2 --stripesize 4294967291 $vg 2>err
+grep "^ Stripe size cannot be larger than" err
+
+# 'lvcreate w/single stripe succeeds with diagnostics to stdout'
+lvcreate -L 64m -n $lv -i1 --stripesize 4 $vg 2> err | tee out
+grep "^ Ignoring stripesize argument with single stripe\$" out
+lvdisplay $vg
+lvremove -ff $vg
+
+# 'lvcreate w/default (64KB) stripe size succeeds with diagnostics to stdout'
+lvcreate -L 64m -n $lv -i2 $vg > out
+grep "^ Using default stripesize" out
+lvdisplay $vg
+check_lv_field_ $vg/$lv stripesize "64.00k"
+lvremove -ff $vg
+
+# 'lvcreate rejects an invalid number of stripes'
+not lvcreate -L 64m -n $lv -i129 $vg 2>err
+grep "^ Number of stripes (129) must be between 1 and 128\$" err
+
+# The case on lvdisplay output is to verify that the LV was not created.
+# 'lvcreate rejects an invalid stripe size'
+not lvcreate -L 64m -n $lv -i2 --stripesize 3 $vg 2>err
+grep "^ Invalid stripe size" err
+case $(lvdisplay $vg) in "") true ;; *) false ;; esac
+
+# Setting max_lv works. (bz490298)
+lvremove -ff $vg
+vgchange -l 3 $vg
+lvcreate -l1 -n $lv1 $vg
+lvcreate -l1 -s -n $lv2 $vg/$lv1
+lvcreate -l1 -n $lv3 $vg
+not lvcreate -l1 -n $lv4 $vg
+
+lvremove -ff $vg/$lv3
+lvcreate -l1 -s -n $lv3 $vg/$lv1
+not lvcreate -l1 -n $lv4 $vg
+not lvcreate -l1 -m1 -n $lv4 $vg
+
+lvremove -ff $vg/$lv3
+lvcreate -l1 -m1 -n $lv3 $vg
+lvs
+vgs -o +max_lv
+not lvcreate -l1 -n $lv4 $vg
+not lvcreate -l1 -m1 -n $lv4 $vg
+
+lvconvert -m0 $vg/$lv3
+lvconvert -m2 -i 1 $vg/$lv3
+lvconvert -m1 $vg/$lv3
+
+not vgchange -l 2
+vgchange -l 4
+vgs $vg
+
+lvremove -ff $vg
+vgchange -l 0 $vg
+
+# lvcreate rejects invalid chunksize, accepts between 4K and 512K
+# validate origin_size
+vgremove -ff $vg
+vgcreate -cn $vg $devs
+lvcreate -L 32m -n $lv1 $vg
+not lvcreate -L 8m -n $lv2 -s --chunksize 3k $vg/$lv1
+not lvcreate -L 8m -n $lv2 -s --chunksize 1024k $vg/$lv1
+lvcreate -L 8m -n $lv2 -s --chunksize 4k $vg/$lv1
+check_lv_field_ $vg/$lv2 chunk_size 4.00k
+check_lv_field_ $vg/$lv2 origin_size 32.00m
+lvcreate -L 8m -n $lv3 -s --chunksize 512k $vg/$lv1
+check_lv_field_ $vg/$lv3 chunk_size 512.00k
+check_lv_field_ $vg/$lv3 origin_size 32.00m
+lvremove -ff $vg
+vgchange -l 0 $vg
+
+# regionsize must be
+# - nonzero (bz186013)
+# - a power of 2 and a multiple of page size
+# - <= size of LV
+not lvcreate -L 32m -n $lv -R0 $vg 2>err
+grep "Non-zero region size must be supplied." err
+not lvcreate -L 32m -n $lv -R 11k $vg
+not lvcreate -L 32m -n $lv -R 1k $vg
+lvcreate -L 32m -n $lv --regionsize 128m -m 1 $vg
+check_lv_field_ $vg/$lv regionsize "32.00m"
+lvremove -ff $vg
+lvcreate -L 32m -n $lv --regionsize 4m -m 1 $vg
+check_lv_field_ $vg/$lv regionsize "4.00m"
+lvremove -ff $vg
+
+# snapshot with virtual origin works
+lvcreate -s --virtualoriginsize 64m -L 32m -n $lv1 $vg
+lvrename $vg/$lv1 $vg/$lv2
+lvcreate -s --virtualoriginsize 64m -L 32m -n $lv1 $vg
+lvchange -a n $vg/$lv1
+lvremove $vg/$lv1
+lvremove -ff $vg
+
+# readahead default (auto), none, #, auto
+lvcreate -L 32m -n $lv $vg
+check_lv_field_ $vg/$lv lv_read_ahead "auto"
+lvremove -ff $vg
+lvcreate -L 32m -n $lv --readahead none $vg
+check_lv_field_ $vg/$lv lv_read_ahead "0"
+lvremove -ff $vg
+lvcreate -L 32m -n $lv --readahead 8k $vg
+check_lv_field_ $vg/$lv lv_read_ahead "8.00k"
+lvremove -ff $vg
+lvcreate -L 32m -n $lv --readahead auto $vg
+check_lv_field_ $vg/$lv lv_read_ahead "auto"
+lvremove -ff $vg
+
diff --git a/test/t-lvextend-percent-extents.sh b/test/t-lvextend-percent-extents.sh
new file mode 100755
index 0000000..d020dec
--- /dev/null
+++ b/test/t-lvextend-percent-extents.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Check extents percentage arguments'
+
+. ./test-utils.sh
+
+aux prepare_vg 2 128
+
+lvcreate -L 64m -n $lv $vg
+
+# 'lvextend rejects both size and extents without PVs'
+not lvextend -l 10 -L 64m $vg/$lv 2>err
+grep "^ Please specify either size or extents but not both.\$" err
+
+# 'lvextend rejects both size and extents with PVs'
+not lvextend -l 10 -L 64m $vg/$lv $dev1 2>err
+grep "^ Please specify either size or extents but not both.\$" err
+
+# 'lvextend accepts no size or extents but one PV - bz154691'
+lvextend $vg/$lv $dev1 >out
+grep "^ Logical volume $lv successfully resized\$" out
+check_pv_field_ $dev1 pv_free "0"
+
+lvremove -f $vg/$lv
+
+# 'lvextend computes necessary free space correctly - bz213552'
+vgsize=$(vgs -o vg_extent_count --noheadings)
+lvcreate -l $vgsize -n $lv $vg
+lvreduce -f -l $(( $vgsize / 2 )) $vg/$lv
+lvextend -l $vgsize $vg/$lv
+
+# 'Reset LV to original size'
+lvremove -f $vg/$lv
+lvcreate -L 64m -n $lv $vg
+
+# 'lvextend accepts no size but extents 100%PVS and two PVs - bz154691'
+lvextend -l +100%PVS $vg/$lv $dev1 $dev2 >out
+grep "^ Logical volume $lv successfully resized\$" out
+check_pv_field_ $dev1 pv_free "0"
+check_pv_field_ $dev2 pv_free "0"
+
+# Exercise the range overlap code. Allocate every 2 extents.
+#
+# Physical Extents
+# 1 2
+#012345678901234567890123
+#
+#aaXXaaXXaaXXaaXXaaXXaaXX - (a)llocated
+#rrrXXXrrrXXXrrrXXXrrrXXX - (r)ange on cmdline
+#ooXXXXXXoXXXooXXXXXXoXXX - (o)verlap of range and allocated
+#
+# Key: a - allocated
+# F - free
+# r - part of a range on the cmdline
+# N - not on cmdline
+#
+# Create the LV with 12 extents, allocated every other 2 extents.
+# Then extend it, with a range of PVs on the cmdline of every other 3 extents.
+# Total number of extents should be 12 + overlap = 12 + 6 = 18.
+# Thus, total size for the LV should be 18 * 4M = 72M
+#
+# 'Reset LV to 12 extents, allocate every other 2 extents'
+create_pvs=`for i in $(seq 0 4 20); do echo -n "\$dev1:$i-$(($i + 1)) "; done`
+lvremove -f $vg/$lv
+lvcreate -l 12 -n $lv $vg $create_pvs
+check_lv_field_ $vg/$lv lv_size "48.00m"
+
+# 'lvextend with partially allocated PVs and extents 100%PVS with PE ranges'
+extend_pvs=`for i in $(seq 0 6 18); do echo -n "\$dev1:$i-$(($i + 2)) "; done`
+lvextend -l +100%PVS $vg/$lv $extend_pvs >out
+grep "^ Logical volume $lv successfully resized\$" out
+check_lv_field_ $vg/$lv lv_size "72.00m"
+
+# Simple seg_count validation; initially create the LV with half the # of
+# extents (should be 1 lv segment), extend it (should go to 2 segments),
+# then reduce (should be back to 1)
+# FIXME: test other segment fields such as seg_size, pvseg_start, pvseg_size
+lvremove -f $vg/$lv
+pe_count=$(pvs -o pv_pe_count --noheadings $dev1)
+pe1=$(( $pe_count / 2 ))
+lvcreate -l $pe1 -n $lv $vg
+pesize=$(lvs -ovg_extent_size --units b --nosuffix --noheadings $vg/$lv)
+segsize=$(( $pe1 * $pesize / 1024 / 1024 ))m
+check_lv_field_ $vg/$lv seg_count 1
+check_lv_field_ $vg/$lv seg_start 0
+check_lv_field_ $vg/$lv seg_start_pe 0
+#check_lv_field_ $vg/$lv seg_size $segsize
+lvextend -l +$(( $pe_count * 1 )) $vg/$lv
+check_lv_field_ $vg/$lv seg_count 2
+lvreduce -f -l -$(( $pe_count * 1 )) $vg/$lv
+check_lv_field_ $vg/$lv seg_count 1
+
diff --git a/test/t-lvextend-snapshot-dmeventd.sh b/test/t-lvextend-snapshot-dmeventd.sh
new file mode 100644
index 0000000..f1ed72f
--- /dev/null
+++ b/test/t-lvextend-snapshot-dmeventd.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+extend() {
+ lvextend --use-policies --config "activation { snapshot_extend_threshold = $1 }" $vg/snap
+}
+
+write() {
+ mount $DM_DEV_DIR/$vg/snap mnt
+ dd if=/dev/zero of=mnt/file$1 bs=1k count=$2
+ umount mnt
+}
+
+percent() {
+ lvs $vg/snap -o snap_percent --noheadings | cut -c4- | cut -d. -f1
+}
+
+which mkfs.ext2 || exit 200
+
+aux prepare_vg 2
+aux prepare_dmeventd
+
+lvcreate -l 8 -n base $vg
+mkfs.ext2 $DM_DEV_DIR/$vg/base
+
+lvcreate -s -l 4 -n snap $vg/base
+lvchange --monitor y $vg/snap
+
+mkdir mnt
+
+write 1 4096
+pre=`percent`
+sleep 10 # dmeventd only checks every 10 seconds :(
+post=`percent`
+
+test $pre = $post
+write 2 5000
+pre=`percent`
+sleep 10 # dmeventd only checks every 10 seconds :(
+post=`percent`
+test $pre -gt $post
diff --git a/test/t-lvextend-snapshot-policy.sh b/test/t-lvextend-snapshot-policy.sh
new file mode 100644
index 0000000..76ea980
--- /dev/null
+++ b/test/t-lvextend-snapshot-policy.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+extend() {
+ lvextend --use-policies --config "activation { snapshot_extend_threshold = $1 }" $vg/snap
+}
+
+write() {
+ mount $DM_DEV_DIR/$vg/snap mnt
+ dd if=/dev/zero of=mnt/file$1 bs=1k count=$2
+ umount mnt
+}
+
+percent() {
+ lvs $vg/snap -o snap_percent --noheadings | cut -c4- | cut -d. -f1
+}
+
+which mkfs.ext2 || exit 200
+
+aux prepare_vg 2
+lvcreate -l 8 -n base $vg
+mkfs.ext2 $DM_DEV_DIR/$vg/base
+
+lvcreate -s -l 4 -n snap $vg/base
+mkdir mnt
+
+write 1 4096
+pre=`percent`
+extend 50
+post=`percent`
+
+test $pre = $post
+write 2 4096
+pre=`percent`
+extend 50
+post=`percent`
+test $pre -gt $post
diff --git a/test/t-lvm-init.sh b/test/t-lvm-init.sh
new file mode 100644
index 0000000..cf324e4
--- /dev/null
+++ b/test/t-lvm-init.sh
@@ -0,0 +1,21 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# tests lvm initialization, and especially negative tests of error paths
+#
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+# invalid units
+not pvs --config 'global { units = "<" }'
+
diff --git a/test/t-lvmcache-exercise.sh b/test/t-lvmcache-exercise.sh
new file mode 100755
index 0000000..aecb4a9
--- /dev/null
+++ b/test/t-lvmcache-exercise.sh
@@ -0,0 +1,23 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 5
+
+vgcreate $vg1 $dev1
+vgcreate $vg2 $dev3
+
+disable_dev $dev1
+pvscan
+vgcreate $vg1 $dev2
+enable_dev $dev1
+pvs
+pvs
diff --git a/test/t-lvresize-mirror.sh b/test/t-lvresize-mirror.sh
new file mode 100644
index 0000000..0d63102
--- /dev/null
+++ b/test/t-lvresize-mirror.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+aux prepare_vg 5 80
+
+# extend 2-way mirror
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvchange -an $vg/$lv1
+lvextend -l+2 $vg/$lv1
+check mirror $vg $lv1 $dev3
+check mirror_images_contiguous $vg $lv1
+lvremove -ff $vg
+
+# reduce 2-way mirror
+lvcreate -l4 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvchange -an $vg/$lv1
+lvreduce -l-2 $vg/$lv1
+check mirror $vg $lv1 $dev3
+lvremove -ff $vg
+
+# extend 2-way mirror (cling if not contiguous)
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0-1
+lvcreate -l1 -n $lv2 $vg $dev1
+lvcreate -l1 -n $lv3 $vg $dev2
+lvchange -an $vg/$lv1
+lvextend -l+2 $vg/$lv1
+check mirror $vg $lv1 $dev3
+check mirror_images_clung $vg $lv1
+lvremove -ff $vg
diff --git a/test/t-lvresize-usage.sh b/test/t-lvresize-usage.sh
new file mode 100755
index 0000000..d9860e9
--- /dev/null
+++ b/test/t-lvresize-usage.sh
@@ -0,0 +1,20 @@
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 2
+
+lvcreate -L 10M -n lv -i2 $vg
+lvresize -l +4 $vg/lv
+lvremove -ff $vg
+
+lvcreate -L 64M -n $lv -i2 $vg
+not lvresize -v -l +4 xxx/$lv
diff --git a/test/t-mdata-strings.sh b/test/t-mdata-strings.sh
new file mode 100755
index 0000000..66d472a
--- /dev/null
+++ b/test/t-mdata-strings.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Test for proper escaping of strings in metadata (bz431474)'
+
+. ./test-utils.sh
+
+aux prepare_devs 1
+
+pv_ugly="__\"!@#\$%^&*,()|@||'\\\"__pv1"
+
+# 'set up temp files, loopback devices'
+name=$(basename "$dev1")
+dmsetup rename "$name" "$PREFIX$pv_ugly"
+dev1=$(dirname "$dev1")/$PREFIX$pv_ugly
+
+# 'pvcreate, vgcreate on filename with backslashed chars'
+pvcreate "$dev1"
+vgcreate $vg "$dev1"
+
+# 'no parse errors and VG really exists'
+vgs 2>err
+not grep "Parse error" err;
+vgs $vg
+
diff --git a/test/t-metadata-balance.sh b/test/t-metadata-balance.sh
new file mode 100755
index 0000000..79570d9
--- /dev/null
+++ b/test/t-metadata-balance.sh
@@ -0,0 +1,232 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 6
+
+echo Make sure we can ignore / un-ignore mdas on a per-PV basis
+for pv_in_vg in 1 0; do
+for mdacp in 1 2; do
+ pvcreate --metadatacopies $mdacp $dev1 $dev2
+ pvcreate --metadatacopies 0 $dev3
+ if [ $pv_in_vg = 1 ]; then
+ vgcreate -c n "$vg" $dev1 $dev2 $dev3
+ fi
+ pvchange --metadataignore y $dev1
+ check_pv_field_ $dev1 pv_mda_count $mdacp
+ check_pv_field_ $dev1 pv_mda_used_count 0
+ check_pv_field_ $dev2 pv_mda_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count $mdacp
+ if [ $pv_in_vg = 1 ]; then
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 2))
+ check_vg_field_ $vg vg_mda_used_count $mdacp
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ fi
+ pvchange --metadataignore n $dev1
+ check_pv_field_ $dev1 pv_mda_count $mdacp
+ check_pv_field_ $dev1 pv_mda_used_count $mdacp
+ if [ $pv_in_vg = 1 ]; then
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 2))
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 2))
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+ fi
+done
+done
+
+# Check if a PV has unignored (used) mdas, and if so, ignore
+pvignore_ () {
+ pv_mda_used_count=$(get_pv_field "$1" pv_mda_used_count)
+ if [ $pv_mda_used_count -ne 0 ]; then
+ pvchange --metadataignore y $1
+ fi
+}
+
+# Check if a PV has ignored mdas, and if so, unignore (make used)
+pvunignore_ () {
+ pv_mda_count=$(get_pv_field "$1" pv_mda_count)
+ pv_mda_used_count=$(get_pv_field "$1" pv_mda_used_count)
+ if [ $pv_mda_count -gt $pv_mda_used_count ]; then
+ pvchange --metadataignore n $1
+ fi
+}
+
+echo Test of vgmetadatacopies with vgcreate and vgchange
+for mdacp in 1 2; do
+ pvcreate --metadatacopies $mdacp $dev1 $dev2 $dev4 $dev5
+ check_pv_field_ $dev1 pv_mda_used_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count $mdacp
+ check_pv_field_ $dev4 pv_mda_used_count $mdacp
+ check_pv_field_ $dev5 pv_mda_used_count $mdacp
+ pvcreate --metadatacopies 0 $dev3
+ vgcreate -c n "$vg" $dev1 $dev2 $dev3
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ echo ensure both --vgmetadatacopies and --metadatacopies accepted
+ vgchange --metadatacopies $(($mdacp * 1)) $vg
+ echo --vgmetadatacopies is persistent on disk
+ echo --vgmetadatacopies affects underlying pv mda ignore
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 1))
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 1))
+ vgchange --vgmetadatacopies $(($mdacp * 2)) $vg
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 2))
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 2))
+ echo allow setting metadatacopies larger than number of PVs
+ vgchange --vgmetadatacopies $(($mdacp * 5)) $vg
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 5))
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 2))
+ echo setting to 0 disables automatic balancing
+ vgchange --vgmetadatacopies unmanaged $vg
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+ echo vgcreate succeeds even when creating a VG w/all ignored mdas
+ pvchange --metadataignore y $dev1 $dev2
+ check_pv_field_ $dev1 pv_mda_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count 0
+ vgcreate -c n "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+ echo vgcreate succeeds with a specific number of metadata copies
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 2)) "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 2))
+ vgremove -f $vg
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 1)) "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 1))
+ vgremove -f $vg
+ echo vgcreate succeeds with a larger value than total metadatacopies
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 5)) "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 5))
+ vgremove -f $vg
+ echo vgcreate succeeds with --vgmetadatacopies unmanaged
+ vgcreate -c n --vgmetadatacopies unmanaged "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+ pvunignore_ $dev1
+ pvunignore_ $dev2
+ pvunignore_ $dev4
+ pvunignore_ $dev5
+ echo vgcreate succeds with small value of --metadatacopies, ignores mdas
+ vgcreate -c n --vgmetadatacopies 1 "$vg" $dev1 $dev2 $dev4 $dev5
+ check_vg_field_ $vg vg_mda_copies 1
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 4))
+ check_vg_field_ $vg vg_mda_used_count 1
+ echo Setting a larger value should trigger non-ignore of mdas
+ vgchange --metadatacopies 3 $vg
+ check_vg_field_ $vg vg_mda_copies 3
+ check_vg_field_ $vg vg_mda_used_count 3
+ echo Setting all should trigger unignore of all mdas
+ vgchange --vgmetadatacopies all $vg
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 4))
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 4))
+ echo --vgmetadatacopies 0 should be unmanaged for vgchange and vgcreate
+ vgchange --vgmetadatacopies 0 $vg
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+ vgcreate -c n --vgmetadatacopies 0 "$vg" $dev1 $dev2 $dev4 $dev5
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove -f $vg
+done
+
+echo Test vgextend / vgreduce with vgmetadatacopies
+for mdacp in 1 2; do
+ pvcreate --metadatacopies $mdacp $dev1 $dev2 $dev4 $dev5
+ pvcreate --metadatacopies 0 $dev3
+ echo Set a large value of vgmetadatacopies
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 5)) "$vg" $dev1 $dev2 $dev3
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 5))
+ echo Ignore mdas on devices to be used for vgextend
+ echo Large value of vgetadatacopies should automatically un-ignore mdas
+ pvchange --metadataignore y $dev4 $dev5
+ check_pv_field_ $dev4 pv_mda_used_count 0
+ vgextend $vg $dev4 $dev5
+ check_pv_field_ $dev4 pv_mda_used_count $mdacp
+ check_pv_field_ $dev5 pv_mda_used_count $mdacp
+ vgremove -f $vg
+ echo Set a small value of vgmetadatacopies
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 1)) "$vg" $dev1 $dev2 $dev3
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 1))
+ echo Ignore mdas on devices to be used for vgextend
+ echo Small value of vgetadatacopies should leave mdas as ignored
+ pvchange --metadataignore y $dev4 $dev5
+ check_pv_field_ $dev4 pv_mda_used_count 0
+ vgextend $vg $dev4 $dev5
+ check_pv_field_ $dev4 pv_mda_used_count 0
+ check_pv_field_ $dev5 pv_mda_used_count 0
+ echo vgreduce of ignored pv w/mda should not trigger any change to ignore bits
+ vgreduce $vg $dev4
+ check_pv_field_ $dev4 pv_mda_used_count 0
+ check_pv_field_ $dev5 pv_mda_used_count 0
+ echo vgreduce of un-ignored pv w/mda should trigger un-ignore on an mda
+ vgreduce $vg $dev1 $dev2 $dev3
+ check_pv_field_ $dev5 pv_mda_used_count $mdacp
+ check_vg_field_ $vg vg_mda_copies $(($mdacp * 1))
+ pvunignore_ $dev1
+ pvunignore_ $dev2
+ echo setting vgmetadatacopies to unmanaged should allow vgextend to add w/out balancing
+ vgchange --vgmetadatacopies unmanaged $vg
+ vgextend $vg $dev1 $dev2
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 3))
+ check_vg_field_ $vg vg_mda_used_count $((mdacp * 3))
+ check_pv_field_ $dev1 pv_mda_used_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count $mdacp
+ vgremove -f $vg
+done
+
+echo Test special situations, vgsplit, vgmerge, etc
+for mdacp in 1 2; do
+ pvcreate --metadatacopies $mdacp $dev1 $dev2 $dev3 $dev4 $dev5
+ vgcreate -c n --vgmetadatacopies 2 $vg1 $dev1 $dev2 $dev3
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 1)) $vg2 $dev4 $dev5
+ echo vgsplit/vgmerge preserves value of metadata copies
+ check_vg_field_ $vg1 vg_mda_copies 2
+ check_vg_field_ $vg2 vg_mda_copies $(($mdacp * 1))
+ vgsplit $vg1 $vg2 $dev1
+ check_vg_field_ $vg2 vg_mda_copies $(($mdacp * 1))
+ vgmerge $vg1 $vg2
+ check_vg_field_ $vg1 vg_mda_copies 2
+ check_vg_field_ $vg1 vg_mda_count $(($mdacp * 5))
+ echo vgsplit into new vg sets proper value of vgmetadatacopies
+ vgsplit --vgmetadatacopies $(($mdacp * 2)) $vg1 $vg2 $dev1 $dev2
+ check_vg_field_ $vg2 vg_mda_copies $(($mdacp * 2))
+ echo vgchange fails if given both vgmetadatacopies and metadatacopies
+ not vgchange --vgmetadatacopies 5 --metadatacopies 7 $vg2
+ vgremove -f $vg1
+ vgremove -f $vg2
+done
+
+echo Test combination of --vgmetadatacopies and pvchange --metadataignore
+for mdacp in 1 2; do
+ pvcreate --metadatacopies $mdacp $dev1 $dev2 $dev3 $dev4 $dev5
+ vgcreate -c n --vgmetadatacopies $(($mdacp * 1)) $vg1 $dev1 $dev2
+ check_vg_field_ $vg1 vg_mda_copies $(($mdacp * 1))
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 1))
+ pvignore_ $dev3
+ echo Ensure vgextend of PVs with ignored MDAs does not add to vg_mda_used_count
+ vgextend $vg1 $dev3
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 1))
+ echo Using pvchange to unignore should update vg_mda_used_count
+ pvchange -f --metadataignore n $dev3
+ check_pv_field_ $dev3 pv_mda_used_count $mdacp
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 2))
+ echo Set unmanaged on the vg should keep ignore bits the same during vgextend
+ vgchange --vgmetadatacopies unmanaged $vg1
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 2))
+ pvunignore_ $dev4
+ vgextend $vg1 $dev4
+ check_pv_field_ $dev4 pv_mda_used_count $mdacp
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 3))
+ echo Using pvchange to ignore should update vg_mda_used_count
+ pvchange -f --metadataignore y $dev4
+ check_pv_field_ $dev4 pv_mda_used_count 0
+ check_vg_field_ $vg1 vg_mda_used_count $(($mdacp * 2))
+ vgremove -f $vg1
+done
diff --git a/test/t-metadata.sh b/test/t-metadata.sh
new file mode 100755
index 0000000..49066c7
--- /dev/null
+++ b/test/t-metadata.sh
@@ -0,0 +1,80 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 0 $dev3
+pvcreate $dev4
+pvcreate --metadatacopies 0 $dev5
+
+vgcreate -c n "$vg" $devs
+lvcreate -n $lv -l 1 -i5 -I256 $vg
+
+pvchange -x n $dev1
+pvchange -x y $dev1
+vgchange -a n $vg
+pvchange --uuid $dev1
+pvchange --uuid $dev2
+vgremove -f $vg
+
+# check that PVs without metadata don't cause too many full device rescans (bz452606)
+for mdacp in 1 0; do
+ pvcreate --metadatacopies $mdacp $devs
+ pvcreate $dev1
+ vgcreate -c n $vg $devs
+ lvcreate -n $lv1 -l 2 -i5 -I256 $vg
+ lvcreate -n $lv2 -m2 -l 2 $vg
+ #lvchange -an $vg
+ lvchange -an $vg/$lv1
+ lvchange -an $vg/$lv2
+ vgchange -ay $vg
+ lvchange -vvvv -an $vg/$lv1 >out$mdacp 2>&1
+ lvchange -vvvv -an $vg/$lv2 >>out$mdacp 2>&1
+ vgremove -f $vg
+done
+not grep "Cached VG .* incorrect PV list" out0
+
+# some M1 metadata tests
+pvcreate -M1 $dev1
+pvcreate -M1 $dev2
+pvcreate -M1 $dev3
+pv3_uuid=$(pvs --noheadings -o pv_uuid $dev3)
+vgcreate -M1 -c n $vg $dev1 $dev2 $dev3
+pvchange --uuid $dev1
+
+# verify pe_start of all M1 PVs
+pv_align="128.00k"
+check_pv_field_ $dev1 pe_start $pv_align
+check_pv_field_ $dev2 pe_start $pv_align
+check_pv_field_ $dev3 pe_start $pv_align
+
+pvs --units k -o name,pe_start,vg_mda_size,vg_name
+
+# upgrade from v1 to v2 metadata
+vgconvert -M2 $vg
+
+# verify pe_start of all M2 PVs
+check_pv_field_ $dev1 pe_start $pv_align
+check_pv_field_ $dev2 pe_start $pv_align
+check_pv_field_ $dev3 pe_start $pv_align
+
+pvs --units k -o name,pe_start,vg_mda_size,vg_name
+
+# create backup and then restore $dev3
+vgcfgbackup -f $TESTDIR/bak-%s $vg
+pvcreate -ff -y --restorefile $TESTDIR/bak-$vg --uuid $pv3_uuid $dev3
+vgcfgrestore -f $TESTDIR/bak-$vg $vg
+
+# verify pe_start of $dev3
+check_pv_field_ $dev3 pe_start $pv_align
diff --git a/test/t-mirror-names.sh b/test/t-mirror-names.sh
new file mode 100644
index 0000000..be6045f
--- /dev/null
+++ b/test/t-mirror-names.sh
@@ -0,0 +1,156 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007-2008 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description="check namings of mirrored LV"
+
+. ./test-utils.sh
+
+# ---------------------------------------------------------------------
+# Utilities
+
+lv_devices_() {
+ local d
+ local lv=$1
+ shift
+ local devices=$*
+
+ local devs=$(lvs -a -odevices --noheadings $lv | sed 's/([0-9]*)//g' |
+ sed 's/ //g' | sed 's/,/ /g')
+
+ for d in $devs; do
+ (echo $devices | grep -q $d) || return 1
+ devices=$(echo $devices | sed "s/$d//")
+ done
+
+ [ "$(echo $devices | sed 's/ //g')" = "" ]
+}
+
+lv_mirror_log_() {
+ local lv=$1
+
+ echo $(lvs -a -omirror_log --noheadings $lv | sed 's/ //g')
+}
+
+lv_convert_lv_() {
+ local lv=$1
+
+ echo $(lvs -a -oconvert_lv --noheadings $lv | sed 's/ //g')
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+aux prepare_vg 5 80
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_() {
+ lvremove -ff $vg
+ if dmsetup table|grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!"
+ return 1
+ fi
+ :
+}
+
+check_and_cleanup_lvs_() {
+ lvs -a -o+devices $vg
+ lvremove -ff $vg
+ if dmsetup table|grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!"
+ return 1
+ fi
+}
+
+prepare_lvs_
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# basic
+
+#COMM "init: lvcreate"
+prepare_lvs_
+
+#COMM "mirror images are ${lv1}_mimage_x"
+lvcreate -l2 -m1 -n $lv1 $vg
+lv_devices_ $vg/$lv1 "$lv1"_mimage_0 "$lv1"_mimage_1
+
+#COMM "mirror log is ${lv1}_mlog"
+lv_mirror_log_ $vg/$lv1 "$lv1"_mlog
+
+# "cleanup"
+check_and_cleanup_lvs_
+
+#COMM "mirror with name longer than 22 characters (bz221322)"
+name="LVwithanamelogerthan22characters_butidontwonttocounthem"
+lvcreate -m1 -l2 -n"$name" $vg
+lvs $vg/"$name"
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# lvrename
+
+#COMM "init: lvrename"
+prepare_lvs_
+
+#COMM "renamed mirror names: $lv1 to $lv2"
+lvcreate -l2 -m1 -n $lv1 $vg
+lvrename $vg/$lv1 $vg/$lv2
+lv_devices_ $vg/$lv2 "$lv2"_mimage_0 "$lv2"_mimage_1
+lv_mirror_log_ $vg/$lv2 "$lv2"_mlog
+
+#COMM "cleanup"
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# lvconvert
+
+#COMM "init: lvconvert"
+prepare_lvs_
+
+#COMM "converting mirror names is ${lv1}_mimagetmp_2"
+lvcreate -l2 -m1 -n $lv1 $vg
+lvconvert -m+1 -i+10 -b $vg/$lv1
+convlv=$(lv_convert_lv_ "$vg/$lv1")
+test "$convlv" = "$lv1"_mimagetmp_2
+lv_devices_ $vg/$lv1 "$convlv" "$lv1"_mimage_2
+lv_devices_ "$vg/$convlv" "$lv1"_mimage_0 "$lv1"_mimage_1
+loglv=$(lv_mirror_log_ "$vg/$convlv")
+test "$loglv" = "$lv1"_mlog
+
+#COMM "mirror log name after re-adding is ${lv1}_mlog" \
+lvconvert --mirrorlog core $vg/$lv1
+lvconvert --mirrorlog disk $vg/$lv1
+convlv=$(lv_convert_lv_ "$vg/$lv1")
+lv_devices_ $vg/$lv1 "$convlv" "$lv1"_mimage_2
+lv_devices_ "$vg/$convlv" "$lv1"_mimage_0 "$lv1"_mimage_1
+loglv=$(lv_mirror_log_ "$vg/$convlv")
+test "$loglv" = "$lv1"_mlog
+
+#COMM "renamed converting mirror names: $lv1 to $lv2" \
+lvrename $vg/$lv1 $vg/$lv2
+convlv=$(lv_convert_lv_ "$vg/$lv2")
+lv_devices_ $vg/$lv2 "$convlv" "$lv2"_mimage_2
+lv_devices_ "$vg/$convlv" "$lv2"_mimage_0 "$lv2"_mimage_1
+loglv=$(lv_mirror_log_ "$vg/$convlv")
+test "$loglv" = "$lv2"_mlog
+
+#COMM "cleanup"
+check_and_cleanup_lvs_
+
+# Temporary mirror log should have "_mlogtmp_<n>" suffix
+# but currently lvconvert doesn't have an option to add the log.
+# If such feature is added in future, a test for that should
+# be added.
+
+# ---------------------------------------------------------------------
diff --git a/test/t-mirror-vgreduce-removemissing.sh b/test/t-mirror-vgreduce-removemissing.sh
new file mode 100755
index 0000000..0f6a8b0
--- /dev/null
+++ b/test/t-mirror-vgreduce-removemissing.sh
@@ -0,0 +1,421 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description="ensure that 'vgreduce --removemissing' works on mirrored LV"
+
+. ./test-utils.sh
+
+lv_is_on_ ()
+{
+ local lv=$vg/$1
+ shift
+ local pvs=$*
+
+ echo "Check if $lv is exactly on PVs $pvs"
+ rm -f out1 out2
+ echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
+
+ lvs -a -o+devices $lv
+ lvs -a -odevices --noheadings $lv | \
+ sed 's/([^)]*)//g; s/[ ,]/\n/g' | sort | uniq > out2
+
+ diff --ignore-blank-lines out1 out2
+}
+
+mimages_are_on_ ()
+{
+ local lv=$1
+ shift
+ local pvs="$*"
+ local mimages
+ local i
+
+ echo "Check if mirror images of $lv are on PVs $pvs"
+ rm -f out1 out2
+ echo $pvs | sed 's/ /\n/g' | sort | uniq > out1
+
+ mimages=$(lvs --noheadings -a -o lv_name $vg | grep "${lv}_mimage_" | \
+ sed 's/\[//g; s/\]//g')
+ for i in $mimages; do
+ echo "Checking $vg/$i"
+ lvs -a -o+devices $vg/$i
+ lvs -a -odevices --noheadings $vg/$i | \
+ sed 's/([^)]*)//g; s/ //g; s/,/ /g' | sort | uniq >> out2
+ done
+
+ diff --ignore-blank-lines out1 out2
+}
+
+mirrorlog_is_on_()
+{
+ local lv="$1"_mlog
+ shift
+ lv_is_on_ $lv $*
+}
+
+lv_is_linear_()
+{
+ echo "Check if $1 is linear LV (i.e. not a mirror)"
+ lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g'
+ lvs -o stripes,attr --noheadings $vg/$1 | sed 's/ //g' | grep -q '^1-'
+}
+
+rest_pvs_()
+{
+ local index=$1
+ local num=$2
+ local rem=""
+ local n
+
+ for n in $(seq 1 $(($index - 1))) $(seq $(($index + 1)) $num); do
+ eval local dev=$\dev$n
+ rem="$rem $dev"
+ done
+
+ echo "$rem"
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+prepare_vg 5
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_()
+{
+ lvremove -ff $vg;
+ if dmsetup table|grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!"
+ return 1
+ fi
+ :
+}
+
+check_and_cleanup_lvs_()
+{
+ lvs -a -o+devices $vg
+ lvremove -ff $vg
+ if dmsetup table|grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!"
+ return 1
+ fi
+}
+
+recover_vg_()
+{
+ enable_dev $*
+ pvcreate -ff $*
+ vgextend $vg $*
+ check_and_cleanup_lvs_
+}
+
+#COMM "check environment setup/cleanup"
+prepare_lvs_
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# one of mirror images has failed
+
+#COMM "basic: fail the 2nd mirror image of 2-way mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev3:0
+lvchange -an $vg/$lv1
+aux mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev3
+disable_dev $dev2
+vgreduce --removemissing --force $vg
+lv_is_linear_ $lv1
+lv_is_on_ $lv1 $dev1
+
+# "cleanup"
+recover_vg_ $dev2
+
+# ---------------------------------------------------------------------
+# LV has 3 images in flat,
+# 1 out of 3 images fails
+
+#COMM test_3way_mirror_fail_1_ <PV# to fail>
+test_3way_mirror_fail_1_()
+{
+ local index=$1
+
+ lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0
+ lvchange -an $vg/$lv1
+ aux mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+ mirrorlog_is_on_ $lv1 $dev4
+ eval disable_dev \$dev$index
+ vgreduce --removemissing --force $vg
+ lvs -a -o+devices $vg
+ mimages_are_on_ $lv1 $(rest_pvs_ $index 3)
+ mirrorlog_is_on_ $lv1 $dev4
+}
+
+for n in $(seq 1 3); do
+ #COMM fail mirror image $(($n - 1)) of 3-way mirrored LV"
+ prepare_lvs_
+ test_3way_mirror_fail_1_ $n
+ eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 3 images in flat,
+# 2 out of 3 images fail
+
+#COMM test_3way_mirror_fail_2_ <PV# NOT to fail>
+test_3way_mirror_fail_2_()
+{
+ local index=$1
+
+ lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev4:0
+ lvchange -an $vg/$lv1
+ mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+ mirrorlog_is_on_ $lv1 $dev4
+ rest_pvs_ $index 3
+ disable_dev $(rest_pvs_ $index 3)
+ vgreduce --force --removemissing $vg
+ lvs -a -o+devices $vg
+ aux lv_is_linear_ $lv1
+ eval lv_is_on_ $lv1 \$dev$n
+}
+
+for n in $(seq 1 3); do
+ #COMM fail mirror images other than mirror image $(($n - 1)) of 3-way mirrored LV
+ prepare_lvs_
+ test_3way_mirror_fail_2_ $n
+ recover_vg_ $(rest_pvs_ $n 3)
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 1 of them is in the temporary mirror for syncing.
+# 1 out of 4 images fails
+
+#COMM test_3way_mirror_plus_1_fail_1_ <PV# to fail>
+test_3way_mirror_plus_1_fail_1_()
+{
+ local index=$1
+
+ lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0
+ lvchange -an $vg/$lv1
+ lvconvert -m+1 $vg/$lv1 $dev4
+ mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
+ mirrorlog_is_on_ $lv1 $dev5
+ eval disable_dev \$dev$n
+ vgreduce --removemissing --force $vg
+ lvs -a -o+devices $vg
+ mimages_are_on_ $lv1 $(rest_pvs_ $index 4)
+ mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+ #COMM "fail mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
+ prepare_lvs_
+ test_3way_mirror_plus_1_fail_1_ $n
+ eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 1 of them is in the temporary mirror for syncing.
+# 3 out of 4 images fail
+
+#COMM test_3way_mirror_plus_1_fail_3_ <PV# NOT to fail>
+test_3way_mirror_plus_1_fail_3_()
+{
+ local index=$1
+
+ lvcreate -l2 -m2 -n $lv1 $vg $dev1 $dev2 $dev3 $dev5:0
+ lvchange -an $vg/$lv1
+ lvconvert -m+1 $vg/$lv1 $dev4
+ mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
+ mirrorlog_is_on_ $lv1 $dev5
+ disable_dev $(rest_pvs_ $index 4)
+ vgreduce --removemissing --force $vg
+ lvs -a -o+devices $vg
+ eval local dev=\$dev$n
+ mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
+ not mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+ #COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (1 converting) mirrored LV"
+ prepare_lvs_
+ test_3way_mirror_plus_1_fail_3_ $n
+ recover_vg_ $(rest_pvs_ $n 4)
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 2 of them are in the temporary mirror for syncing.
+# 1 out of 4 images fail
+
+# test_2way_mirror_plus_2_fail_1_ <PV# to fail>
+test_2way_mirror_plus_2_fail_1_()
+{
+ local index=$1
+
+ lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+ lvchange -an $vg/$lv1
+ lvconvert -m+2 $vg/$lv1 $dev3 $dev4
+ mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
+ mirrorlog_is_on_ $lv1 $dev5
+ eval disable_dev \$dev$n
+ vgreduce --removemissing --force $vg
+ lvs -a -o+devices $vg
+ mimages_are_on_ $lv1 $(rest_pvs_ $index 4)
+ mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+ #COMM "fail mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV"
+ prepare_lvs_
+ test_2way_mirror_plus_2_fail_1_ $n
+ eval recover_vg_ \$dev$n
+done
+
+# ---------------------------------------------------------------------
+# LV has 4 images, 2 of them are in the temporary mirror for syncing.
+# 3 out of 4 images fail
+
+# test_2way_mirror_plus_2_fail_3_ <PV# NOT to fail>
+test_2way_mirror_plus_2_fail_3_()
+{
+ local index=$1
+
+ lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+ lvchange -an $vg/$lv1
+ lvconvert -m+2 $vg/$lv1 $dev3 $dev4
+ mimages_are_on_ $lv1 $dev1 $dev2 $dev3 $dev4
+ mirrorlog_is_on_ $lv1 $dev5
+ disable_dev $(rest_pvs_ $index 4)
+ vgreduce --removemissing --force $vg
+ lvs -a -o+devices $vg
+ eval local dev=\$dev$n
+ mimages_are_on_ $lv1 $dev || lv_is_on_ $lv1 $dev
+ not mirrorlog_is_on_ $lv1 $dev5
+}
+
+for n in $(seq 1 4); do
+ #COMM "fail mirror images other than mirror image $(($n - 1)) of 4-way (2 converting) mirrored LV"
+ prepare_lvs_
+ test_2way_mirror_plus_2_fail_3_ $n
+ recover_vg_ $(rest_pvs_ $n 4)
+done
+
+# ---------------------------------------------------------------------
+# log device is gone (flat mirror and stacked mirror)
+
+#COMM "fail mirror log of 2-way mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev5
+disable_dev $dev5
+vgreduce --removemissing --force $vg
+mimages_are_on_ $lv1 $dev1 $dev2
+not mirrorlog_is_on_ $lv1 $dev5
+recover_vg_ $dev5
+
+#COMM "fail mirror log of 3-way (1 converting) mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+lvconvert -m+1 $vg/$lv1 $dev3
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+mirrorlog_is_on_ $lv1 $dev5
+disable_dev $dev5
+vgreduce --removemissing --force $vg
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+not mirrorlog_is_on_ $lv1 $dev5
+recover_vg_ $dev5
+
+# ---------------------------------------------------------------------
+# all images are gone (flat mirror and stacked mirror)
+
+#COMM "fail all mirror images of 2-way mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev5
+disable_dev $dev1 $dev2
+vgreduce --removemissing --force $vg
+not lvs $vg/$lv1
+recover_vg_ $dev1 $dev2
+
+#COMM "fail all mirror images of 3-way (1 converting) mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+lvconvert -m+1 $vg/$lv1 $dev3
+mimages_are_on_ $lv1 $dev1 $dev2 $dev3
+mirrorlog_is_on_ $lv1 $dev5
+disable_dev $dev1 $dev2 $dev3
+vgreduce --removemissing --force $vg
+not lvs $vg/$lv1
+recover_vg_ $dev1 $dev2 $dev3
+
+# ---------------------------------------------------------------------
+# Multiple LVs
+
+#COMM "fail a mirror image of one of mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1
+lvchange -an $vg/$lv2
+mimages_are_on_ $lv1 $dev1 $dev2
+mimages_are_on_ $lv2 $dev3 $dev4
+mirrorlog_is_on_ $lv1 $dev5
+mirrorlog_is_on_ $lv2 $dev5
+disable_dev $dev2
+vgreduce --removemissing --force $vg
+mimages_are_on_ $lv2 $dev3 $dev4
+mirrorlog_is_on_ $lv2 $dev5
+lv_is_linear_ $lv1
+lv_is_on_ $lv1 $dev1
+recover_vg_ $dev2
+
+#COMM "fail mirror images, one for each mirrored LV"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+lvcreate -l2 -m1 -n $lv2 $vg $dev3 $dev4 $dev5:1
+lvchange -an $vg/$lv2
+mimages_are_on_ $lv1 $dev1 $dev2
+mimages_are_on_ $lv2 $dev3 $dev4
+mirrorlog_is_on_ $lv1 $dev5
+mirrorlog_is_on_ $lv2 $dev5
+disable_dev $dev2
+disable_dev $dev4
+vgreduce --removemissing --force $vg
+lv_is_linear_ $lv1
+lv_is_on_ $lv1 $dev1
+lv_is_linear_ $lv2
+lv_is_on_ $lv2 $dev3
+recover_vg_ $dev2 $dev4
+
+# ---------------------------------------------------------------------
+# no failure
+
+#COMM "no failures"
+prepare_lvs_
+lvcreate -l2 -m1 -n $lv1 $vg $dev1 $dev2 $dev5:0
+lvchange -an $vg/$lv1
+mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev5
+vgreduce --removemissing --force $vg
+mimages_are_on_ $lv1 $dev1 $dev2
+mirrorlog_is_on_ $lv1 $dev5
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
diff --git a/test/t-nomda-missing.sh b/test/t-nomda-missing.sh
new file mode 100644
index 0000000..fb0b882
--- /dev/null
+++ b/test/t-nomda-missing.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_devs 4
+pvcreate $dev1 $dev2
+pvcreate --metadatacopies 0 $dev3 $dev4
+vgcreate -c n $vg $dev1 $dev2 $dev3 $dev4
+
+lvcreate -l1 -n linear1 $vg $dev1
+lvcreate -l1 -n linear2 $vg $dev2
+lvcreate -l2 -n linear12 $vg $dev1:4 $dev2:4
+
+lvcreate -l1 -n origin1 $vg $dev1
+lvcreate -s $vg/origin1 -l1 -n s_napshot2 $dev2
+
+lvcreate -l1 -m1 -n mirror12 --mirrorlog core $vg $dev1 $dev2
+lvcreate -l1 -m1 -n mirror123 $vg $dev1 $dev2 $dev3
+
+vgchange -a n $vg
+disable_dev $dev1
+not vgchange -a y $vg
+not vgck $vg
+
+check inactive $vg linear1
+check active $vg linear2
+check inactive $vg origin1
+check inactive $vg s_napshot2
+check inactive $vg linear12
+check inactive $vg mirror12
+check inactive $vg mirror123
+
+vgchange -a n $vg
+enable_dev $dev1
+disable_dev $dev2
+not vgchange -a y $vg
+not vgck $vg
+
+check active $vg linear1
+check inactive $vg linear2
+check inactive $vg linear12
+check inactive $vg origin1
+check inactive $vg s_napshot2
+check inactive $vg mirror12
+check inactive $vg mirror123
+
+vgchange -a n $vg
+enable_dev $dev2
+disable_dev $dev3
+not vgchange -a y $vg
+not vgck $vg
+
+check active $vg origin1
+check active $vg s_napshot2
+check active $vg linear1
+check active $vg linear2
+check active $vg linear12
+check inactive $vg mirror123
+check active $vg mirror12
+
+vgchange -a n $vg
+enable_dev $dev3
+disable_dev $dev4
+vgchange -a y $vg
+not vgck $vg
+
+check active $vg origin1
+check active $vg s_napshot2
+check active $vg linear1
+check active $vg linear2
+check active $vg linear12
+check active $vg mirror12
+check active $vg mirror123
diff --git a/test/t-pool-labels.sh b/test/t-pool-labels.sh
new file mode 100755
index 0000000..57f4f9a
--- /dev/null
+++ b/test/t-pool-labels.sh
@@ -0,0 +1,39 @@
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+# create the old GFS pool labeled linear devices
+create_pool_label_()
+{
+ # FIXME
+ # echo -e is bashism, dash builtin sh doesn't do \xNN in printf either
+ # printf comes from coreutils, and is probably not posix either
+ env printf "\x01\x16\x70\x06\x5f\xcf\xff\xb9\xf8\x24\x8apool1" | dd of=$2 bs=5 seek=1 conv=notrunc
+ env printf "\x04\x01\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0$1\x68\x01\x16\x70\x00\x00\x00\x00\x00\x06\x5f\xd0" | dd of=$2 bs=273 seek=1 conv=notrunc
+}
+
+env printf "" || exit 200 # skip if printf is not available
+
+aux prepare_devs 2
+
+create_pool_label_ 0 "$dev1"
+create_pool_label_ 1 "$dev2"
+
+# check that pvcreate fails without -ff on the pool device
+not pvcreate "$dev1"
+
+# check that vgdisplay and pvcreate -ff works with the pool device
+vgdisplay --config 'global { locking_type = 0 }'
+disable_dev "$dev2"
+# FIXME! since pool1 cannot be opened, vgdisplay gives error... should we say
+# "not" there instead, checking that it indeed does fail?
+vgdisplay --config 'global { locking_type = 0 }' || true
+pvcreate -ff -y "$dev1"
diff --git a/test/t-pv-range-overflow.sh b/test/t-pv-range-overflow.sh
new file mode 100755
index 0000000..04674cb
--- /dev/null
+++ b/test/t-pv-range-overflow.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Ensure that pvmove diagnoses PE-range values 2^32 and larger.'
+
+. ./test-utils.sh
+
+aux prepare_vg 2
+
+lvcreate -L4 -n"$lv" $vg
+
+# Test for the bogus diagnostic reported in BZ 284771
+# http://bugzilla.redhat.com/284771.
+# 'run pvmove with an unrecognized LV name to show bad diagnostic'
+not pvmove -v -nbogus $dev1 $dev2 2> err
+grep " Logical volume bogus not found." err
+
+# With lvm-2.02.28 and earlier, on a system with 64-bit "long int",
+# the PE range parsing code would accept values up to 2^64-1, but would
+# silently truncate them to int32_t. I.e., $dev1:$(echo 2^32|bc) would be
+# treated just like $dev1:0.
+# 'run the offending pvmove command'
+not pvmove -v -n$lv $dev1:4294967296 $dev2
+
diff --git a/test/t-pvchange-usage.sh b/test/t-pvchange-usage.sh
new file mode 100755
index 0000000..0f69249
--- /dev/null
+++ b/test/t-pvchange-usage.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Test pvchange option values'
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mda in 0 1 2
+do
+# "setup pv with metadatacopies = $mda"
+ pvcreate $dev4
+ pvcreate --metadatacopies $mda $dev1
+ vgcreate $vg1 $dev1 $dev4
+
+# "pvchange adds/dels tag to pvs with metadatacopies = $mda "
+ pvchange $dev1 --addtag test$mda
+ check_pv_field_ $dev1 pv_tags test$mda
+ pvchange $dev1 --deltag test$mda
+ check_pv_field_ $dev1 pv_tags ""
+
+# "vgchange disable/enable allocation for pvs with metadatacopies = $mda (bz452982)"
+ pvchange $dev1 -x n
+ check_pv_field_ $dev1 pv_attr --
+ pvchange $dev1 -x y
+ check_pv_field_ $dev1 pv_attr a-
+
+# 'remove pv'
+ vgremove $vg1
+ pvremove $dev1 $dev4
+done
+
+# "pvchange uuid"
+pvcreate --metadatacopies 0 $dev1
+pvcreate --metadatacopies 2 $dev2
+vgcreate $vg1 $dev1 $dev2
+pvchange -u $dev1
+pvchange -u $dev2
+vg_validate_pvlv_counts_ $vg1 2 0 0
+pvchange -u --all
+vg_validate_pvlv_counts_ $vg1 2 0 0
+
+# "pvchange rejects uuid change under an active lv"
+lvcreate -l 16 -i 2 -n $lv --alloc anywhere $vg1
+vg_validate_pvlv_counts_ $vg1 2 1 0
+not pvchange -u $dev1
+lvchange -an "$vg1"/"$lv"
+pvchange -u $dev1
+
+# "cleanup"
+lvremove -f "$vg1"/"$lv"
+vgremove $vg1
+
+# "pvchange reject --addtag to lvm1 pv"
+pvcreate -M1 $dev1
+not pvchange $dev1 --addtag test
+
diff --git a/test/t-pvcreate-metadata0.sh b/test/t-pvcreate-metadata0.sh
new file mode 100755
index 0000000..8447ce5
--- /dev/null
+++ b/test/t-pvcreate-metadata0.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# Testcase for bugzilla #450651
+# also checks that vgremove properly removes all lv devices in the right order
+#
+# 'Test pvcreate without metadata on all pvs'
+
+. ./test-utils.sh
+
+aux prepare_devs 2 128
+
+#lv_snap=$lv2
+pvcreate "$dev1"
+pvcreate --metadatacopies 0 "$dev2"
+
+# "check lv snapshot"
+vgcreate -c n "$vg" "$dev1" "$dev2"
+lvcreate -n "$lv" -l 60%FREE "$vg"
+lvcreate -s -n $lv2 -l 10%FREE "$vg"/"$lv"
+pvdisplay
+lvdisplay
+vgremove -f "$vg"
diff --git a/test/t-pvcreate-operation-md.sh b/test/t-pvcreate-operation-md.sh
new file mode 100644
index 0000000..cab63a0
--- /dev/null
+++ b/test/t-pvcreate-operation-md.sh
@@ -0,0 +1,143 @@
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# skip this test if mdadm or sfdisk (or others) aren't available
+which mdadm || exit 200
+which sfdisk || exit 200
+which perl || exit 200
+which awk || exit 200
+which cut || exit 200
+
+test -f /proc/mdstat && grep -q raid0 /proc/mdstat || \
+modprobe raid0 || exit 200
+
+. ./test-utils.sh
+
+prepare_lvmconf '[ "a|/dev/md.*|", "a/dev\/mapper\/.*$/", "r/.*/" ]'
+aux prepare_devs 2
+
+# Have MD use a non-standard name to avoid colliding with an existing MD device
+# - mdadm >= 3.0 requires that non-standard device names be in /dev/md/
+# - newer mdadm _completely_ defers to udev to create the associated device node
+mdadm_maj=$(mdadm --version 2>&1 | perl -pi -e 's|.* v(\d+).*|\1|')
+[ $mdadm_maj -ge 3 ] && \
+ mddev=/dev/md/md_lvm_test0 || \
+ mddev=/dev/md_lvm_test0
+
+cleanup_md() {
+ # sleeps offer hack to defeat: 'md: md127 still in use'
+ # see: https://bugzilla.redhat.com/show_bug.cgi?id=509908#c25
+ sleep 2
+ mdadm --stop $mddev || true
+ if [ -b "$mddev" ]; then
+ # mdadm doesn't always cleanup the device node
+ sleep 2
+ rm -f $mddev
+ fi
+}
+
+cleanup_md_and_teardown() {
+ cleanup_md
+ teardown
+}
+
+# create 2 disk MD raid0 array (stripe_width=128K)
+test -b "$mddev" && exit 200
+mdadm --create --metadata=1.0 $mddev --auto=md --level 0 --raid-devices=2 --chunk 64 $dev1 $dev2
+trap 'aux cleanup_md_and_teardown' EXIT # cleanup this MD device at the end of the test
+test -b "$mddev" || exit 200
+
+# Test alignment of PV on MD without any MD-aware or topology-aware detection
+# - should treat $mddev just like any other block device
+pv_align="1.00m"
+pvcreate --metadatasize 128k \
+ --config 'devices {md_chunk_alignment=0 data_alignment_detection=0 data_alignment_offset_detection=0}' \
+ $mddev
+check_pv_field_ $mddev pe_start $pv_align
+
+# Test md_chunk_alignment independent of topology-aware detection
+pv_align="1.00m"
+pvcreate --metadatasize 128k \
+ --config 'devices {data_alignment_detection=0 data_alignment_offset_detection=0}' \
+ $mddev
+check_pv_field_ $mddev pe_start $pv_align
+
+# Get linux minor version
+linux_minor=$(echo `uname -r` | cut -d'.' -f3 | cut -d'-' -f1)
+
+# Test newer topology-aware alignment detection
+# - first added to 2.6.31 but not "reliable" until 2.6.33
+if [ $linux_minor -ge 33 ]; then
+ pv_align="1.00m"
+ # optimal_io_size=131072, minimum_io_size=65536
+ pvcreate --metadatasize 128k \
+ --config 'devices { md_chunk_alignment=0 }' $mddev
+ check_pv_field_ $mddev pe_start $pv_align
+fi
+
+# partition MD array directly, depends on blkext in Linux >= 2.6.28
+if [ $linux_minor -ge 28 ]; then
+ # create one partition
+ sfdisk $mddev <<EOF
+,,83
+EOF
+ # make sure partition on MD is _not_ removed
+ # - tests partition -> parent lookup via sysfs paths
+ not pvcreate --metadatasize 128k $mddev
+
+ # verify alignment_offset is accounted for in pe_start
+ # - topology infrastructure is available in Linux >= 2.6.31
+ # - also tests partition -> parent lookup via sysfs paths
+
+ # Oh joy: need to lookup /sys/block/md127 rather than /sys/block/md_lvm_test0
+ mddev_maj_min=$(ls -lL $mddev | awk '{ print $5 $6 }' | perl -pi -e 's|,|:|')
+ mddev_p_sysfs_name=$(echo /sys/dev/block/${mddev_maj_min}/*p1)
+ base_mddev_p=`basename $mddev_p_sysfs_name`
+ mddev_p=/dev/${base_mddev_p}
+
+ # Checking for 'alignment_offset' in sysfs implies Linux >= 2.6.31
+ # but reliable alignment_offset support requires kernel.org Linux >= 2.6.33
+ sysfs_alignment_offset=/sys/dev/block/${mddev_maj_min}/${base_mddev_p}/alignment_offset
+ [ -f $sysfs_alignment_offset -a $linux_minor -ge 33 ] && \
+ alignment_offset=`cat $sysfs_alignment_offset` || \
+ alignment_offset=0
+
+ if [ $alignment_offset -gt 0 ]; then
+ # default alignment is 1M, add alignment_offset
+ pv_align=$((1048576+$alignment_offset))B
+ pvcreate --metadatasize 128k $mddev_p
+ check_pv_field_ $mddev_p pe_start $pv_align "--units b"
+ pvremove $mddev_p
+ fi
+fi
+
+# Test newer topology-aware alignment detection w/ --dataalignment override
+if [ $linux_minor -ge 33 ]; then
+ cleanup_md
+ pvcreate -f $dev1
+ pvcreate -f $dev2
+
+ # create 2 disk MD raid0 array (stripe_width=2M)
+ test -b "$mddev" && exit 200
+ mdadm --create --metadata=1.0 $mddev --auto=md --level 0 --raid-devices=2 --chunk 1024 $dev1 $dev2
+ test -b "$mddev" || exit 200
+
+ # optimal_io_size=2097152, minimum_io_size=1048576
+ pv_align="2.00m"
+ pvcreate --metadatasize 128k \
+ --config 'devices { md_chunk_alignment=0 }' $mddev
+ check_pv_field_ $mddev pe_start $pv_align
+
+ # now verify pe_start alignment override using --dataalignment
+ pv_align="192.00k"
+ pvcreate --dataalignment 64k --metadatasize 128k \
+ --config 'devices { md_chunk_alignment=0 }' $mddev
+ check_pv_field_ $mddev pe_start $pv_align
+fi
diff --git a/test/t-pvcreate-operation.sh b/test/t-pvcreate-operation.sh
new file mode 100755
index 0000000..2c94696
--- /dev/null
+++ b/test/t-pvcreate-operation.sh
@@ -0,0 +1,121 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mdatype in 1 2
+do
+# pvcreate (lvm$mdatype) refuses to overwrite an mounted filesystem (bz168330)
+ test ! -d $TESTDIR/mnt && mkdir $TESTDIR/mnt
+ if mke2fs $dev1; then
+ mount $dev1 $TESTDIR/mnt
+ not pvcreate -M$mdatype $dev1 2>err
+ grep "Can't open $dev1 exclusively. Mounted filesystem?" err
+ umount $dev1
+ fi
+
+# pvcreate (lvm$mdatype) succeeds when run repeatedly (pv not in a vg) (bz178216)
+ pvcreate -M$mdatype $dev1
+ pvcreate -M$mdatype $dev1
+ pvremove -f $dev1
+
+# pvcreate (lvm$mdatype) fails when PV belongs to VG" \
+ pvcreate -M$mdatype $dev1
+ vgcreate -M$mdatype $vg1 $dev1
+ not pvcreate -M$mdatype $dev1
+
+ vgremove -f $vg1
+ pvremove -f $dev1
+
+# pvcreate (lvm$mdatype) fails when PV1 does and PV2 does not belong to VG
+ pvcreate -M$mdatype $dev1
+ pvcreate -M$mdatype $dev2
+ vgcreate -M$mdatype $vg1 $dev1
+
+# pvcreate a second time on $dev2 and $dev1
+ not pvcreate -M$mdatype $dev2 $dev1
+
+ vgremove -f $vg1
+ pvremove -f $dev2
+ pvremove -f $dev1
+
+# NOTE: Force pvcreate after test completion to ensure clean device
+#test_expect_success \
+# "pvcreate (lvm$mdatype) fails on md component device" \
+# 'mdadm -C -l raid0 -n 2 /dev/md0 $dev1 $dev2 &&
+# pvcreate -M$mdatype $dev1;
+# status=$?; echo status=$status; test $status != 0 &&
+# mdadm --stop /dev/md0 &&
+# pvcreate -ff -y -M$mdatype $dev1 $dev2 &&
+# pvremove -f $dev1 $dev2'
+done
+
+# pvcreate (lvm2) fails without -ff when PV with metadatacopies=0 belongs to VG
+pvcreate --metadatacopies 0 $dev1
+pvcreate --metadatacopies 1 $dev2
+vgcreate $vg1 $dev1 $dev2
+not pvcreate $dev1
+vgremove -f $vg1
+pvremove -f $dev2
+pvremove -f $dev1
+
+# pvcreate (lvm2) succeeds with -ff when PV with metadatacopies=0 belongs to VG
+pvcreate --metadatacopies 0 $dev1
+pvcreate --metadatacopies 1 $dev2
+vgcreate $vg1 $dev1 $dev2
+pvcreate -ff -y $dev1
+vgreduce --removemissing $vg1
+vgremove -ff $vg1
+pvremove -f $dev2
+pvremove -f $dev1
+
+for i in 0 1 2 3
+do
+# pvcreate (lvm2) succeeds writing LVM label at sector $i
+ pvcreate --labelsector $i $dev1
+ dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE;
+ pvremove -f $dev1
+done
+
+# pvcreate (lvm2) fails writing LVM label at sector 4
+not pvcreate --labelsector 4 $dev1
+
+backupfile=$PREFIX.mybackupfile
+uuid1=freddy-fred-fred-fred-fred-fred-freddy
+uuid2=freddy-fred-fred-fred-fred-fred-fredie
+bogusuuid=fred
+
+# pvcreate rejects uuid option with less than 32 characters
+not pvcreate --norestorefile --uuid $bogusuuid $dev1
+
+# pvcreate rejects uuid option without restorefile
+not pvcreate --uuid $uuid1 $dev1
+
+# pvcreate rejects uuid already in use
+pvcreate --norestorefile --uuid $uuid1 $dev1
+not pvcreate --norestorefile --uuid $uuid1 $dev2
+
+# pvcreate rejects non-existent file given with restorefile
+not pvcreate --uuid $uuid1 --restorefile $backupfile $dev1
+
+# pvcreate rejects restorefile with uuid not found in file
+pvcreate --norestorefile --uuid $uuid1 $dev1
+vgcfgbackup -f $backupfile
+not pvcreate --uuid $uuid2 --restorefile $backupfile $dev2
+
+# pvcreate wipes swap signature when forced
+dd if=/dev/zero of=$dev1 bs=1024 count=64
+mkswap $dev1
+blkid -c /dev/null $dev1 | grep "swap"
+pvcreate -f $dev1
+# blkid cannot make up its mind whether not finding anything it knows is a failure or not
+(blkid -c /dev/null $dev1 || true) | not grep "swap"
diff --git a/test/t-pvcreate-usage.sh b/test/t-pvcreate-usage.sh
new file mode 100755
index 0000000..35dc1c0
--- /dev/null
+++ b/test/t-pvcreate-usage.sh
@@ -0,0 +1,191 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='Test pvcreate option values'
+PAGESIZE=$(getconf PAGESIZE)
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+#COMM 'pvcreate rejects negative setphysicalvolumesize'
+not pvcreate --setphysicalvolumesize -1024 $dev1
+
+#COMM 'pvcreate rejects negative metadatasize'
+not pvcreate --metadatasize -1024 $dev1
+
+# x. metadatasize 0, defaults to 255
+# FIXME: unable to check default value, not in reporting cmds
+# should default to 255 according to code
+# check_pv_field_ pv_mda_size 255
+#COMM 'pvcreate accepts metadatasize 0'
+pvcreate --metadatasize 0 $dev1
+pvremove $dev1
+
+#Verify vg_mda_size is smaller pv_mda_size
+pvcreate --metadatasize 512k $dev1
+pvcreate --metadatasize 96k $dev2
+vgcreate $vg $dev1 $dev2
+compare_two_fields_ vgs $vg vg_mda_size pvs $dev2 pv_mda_size
+vgremove -ff $vg
+
+# x. metadatasize too large
+# For some reason we allow this, even though there's no room for data?
+##COMM 'pvcreate rejects metadatasize too large'
+#not pvcreate --metadatasize 100000000000000 $dev1
+
+#COMM 'pvcreate rejects metadatacopies < 0'
+not pvcreate --metadatacopies -1 $dev1
+
+#COMM 'pvcreate accepts metadatacopies = 0, 1, 2'
+for j in metadatacopies pvmetadatacopies
+do
+pvcreate --$j 0 $dev1
+pvcreate --$j 1 $dev2
+pvcreate --$j 2 $dev3
+check_pv_field_ $dev1 pv_mda_count 0
+check_pv_field_ $dev2 pv_mda_count 1
+check_pv_field_ $dev3 pv_mda_count 2
+pvremove $dev1
+pvremove $dev2
+pvremove $dev3
+done
+
+#COMM 'pvcreate rejects metadatacopies > 2'
+not pvcreate --metadatacopies 3 $dev1
+
+#COMM 'pvcreate rejects invalid device'
+not pvcreate $dev1bogus
+
+#COMM 'pvcreate rejects labelsector < 0'
+not pvcreate --labelsector -1 $dev1
+
+#COMM 'pvcreate rejects labelsector > 1000000000000'
+not pvcreate --labelsector 1000000000000 $dev1
+
+# other possibilites based on code inspection (not sure how hard)
+# x. device too small (min of 512 * 1024 KB)
+# x. device filtered out
+# x. unable to open /dev/urandom RDONLY
+# x. device too large (pe_count > UINT32_MAX)
+# x. device read-only
+# x. unable to open device readonly
+# x. BLKGETSIZE64 fails
+# x. set size to value inconsistent with device / PE size
+
+#COMM 'pvcreate basic dataalignment sanity checks'
+not pvcreate --dataalignment -1 $dev1
+not pvcreate -M 1 --dataalignment 1 $dev1
+not pvcreate --dataalignment 1e $dev1
+
+#COMM 'pvcreate always rounded up to page size for start of device'
+#pvcreate --metadatacopies 0 --dataalignment 1 $dev1
+# amuse shell experts
+#check_pv_field_ $dev1 pe_start $(($(getconf PAGESIZE)/1024))".00k"
+
+#COMM 'pvcreate sets data offset directly'
+pvcreate --dataalignment 512k $dev1
+check_pv_field_ $dev1 pe_start 512.00k
+
+#COMM 'vgcreate/vgremove do not modify data offset of existing PV'
+vgcreate $vg $dev1 --config 'devices { data_alignment = 1024 }'
+check_pv_field_ $dev1 pe_start 512.00k
+vgremove $vg --config 'devices { data_alignment = 1024 }'
+check_pv_field_ $dev1 pe_start 512.00k
+
+#COMM 'pvcreate sets data offset next to mda area'
+pvcreate --metadatasize 100k --dataalignment 100k $dev1
+check_pv_field_ $dev1 pe_start 200.00k
+
+# metadata area start is aligned according to pagesize
+# pagesize should be 64k or 4k ...
+if [ $PAGESIZE -eq 65536 ] ; then
+ pv_align="192.50k"
+else
+ pv_align="133.00k"
+fi
+
+pvcreate --metadatasize 128k --dataalignment 3.5k $dev1
+check_pv_field_ $dev1 pe_start $pv_align
+
+pvcreate --metadatasize 128k --metadatacopies 2 --dataalignment 3.5k $dev1
+check_pv_field_ $dev1 pe_start $pv_align
+
+# data area is aligned to 1M by default,
+# data area start is shifted by the specified alignment_offset
+pv_align="1052160B" # 1048576 + (7*512)
+pvcreate --metadatasize 128k --dataalignmentoffset 7s $dev1
+check_pv_field_ $dev1 pe_start $pv_align "--units b"
+
+# 2nd metadata area is created without problems when
+# data area start is shifted by the specified alignment_offset
+pvcreate --metadatasize 128k --metadatacopies 2 --dataalignmentoffset 7s $dev1
+check_pv_field_ $dev1 pv_mda_count 2
+# FIXME: compare start of 2nd mda with and without --dataalignmentoffset
+
+#COMM 'pv with LVM1 compatible data alignment can be convereted'
+#compatible == LVM1_PE_ALIGN == 64k
+pvcreate --dataalignment 256k $dev1
+vgcreate -s 1m $vg $dev1
+vgconvert -M1 $vg
+vgconvert -M2 $vg
+check_pv_field_ $dev1 pe_start 256.00k
+vgremove $vg
+
+#COMM 'pv with LVM1 incompatible data alignment cannot be convereted'
+pvcreate --dataalignment 10k $dev1
+vgcreate -s 1m $vg $dev1
+not vgconvert -M1 $vg
+vgremove $vg
+
+#COMM 'vgcfgrestore allows pe_start=0'
+#basically it produces nonsense, but it tests vgcfgrestore,
+#not that final cfg is usable...
+pvcreate --metadatacopies 0 $dev1
+pvcreate $dev2
+vgcreate $vg $dev1 $dev2
+vgcfgbackup -f "$(pwd)/backup.$$" $vg
+sed 's/pe_start = [0-9]*/pe_start = 0/' "$(pwd)/backup.$$" > "$(pwd)/backup.$$1"
+vgcfgrestore -f "$(pwd)/backup.$$1" $vg
+check_pv_field_ $dev1 pe_start 0
+check_pv_field_ $dev2 pe_start 0
+vgremove $vg
+
+echo test pvcreate --metadataignore
+for pv_in_vg in 1 0; do
+for mdacp in 1 2; do
+for ignore in y n; do
+ echo pvcreate --metadataignore has proper mda_count and mda_used_count
+ pvcreate --metadatacopies $mdacp --metadataignore $ignore $dev1 $dev2
+ check_pv_field_ $dev1 pv_mda_count $mdacp
+ check_pv_field_ $dev2 pv_mda_count $mdacp
+ if [ $ignore = y ]; then
+ check_pv_field_ $dev1 pv_mda_used_count 0
+ check_pv_field_ $dev2 pv_mda_used_count 0
+ else
+ check_pv_field_ $dev1 pv_mda_used_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count $mdacp
+ fi
+ echo vgcreate has proper vg_mda_count and vg_mda_used_count
+ if [ $pv_in_vg = 1 ]; then
+ vgcreate -c n "$vg" $dev1 $dev2
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 2))
+ if [ $ignore = y ]; then
+ check_vg_field_ $vg vg_mda_used_count 1
+ else
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 2))
+ fi
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove $vg
+ fi
+done
+done
+done
diff --git a/test/t-pvmove-basic.sh b/test/t-pvmove-basic.sh
new file mode 100755
index 0000000..44b533c
--- /dev/null
+++ b/test/t-pvmove-basic.sh
@@ -0,0 +1,374 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2007 NEC Corporation
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description="ensure that pvmove works with basic options"
+
+. ./test-utils.sh
+
+# ---------------------------------------------------------------------
+# Utilities
+
+lvdev_() {
+ echo "$DM_DEV_DIR/$1/$2"
+}
+
+lv_is_on_() {
+ local lv=$1 #allready vg/lv
+ shift 1
+ lvs -a -odevices --noheadings $lv | sed 's/,/\n/g' > out
+#is on all specified devs
+ for d in $*; do grep "$d(" out; done
+#isn't on any other dev (we are set -e remember)
+ for d in $*; do ! grep -v "$d(" out; done
+ return 0
+}
+
+save_dev_sum_() {
+ mkfs.ext3 $1 > /dev/null && md5sum $1 > md5.$(basename $1)
+}
+
+check_dev_sum_() {
+ md5sum $1 > md5.tmp && cmp md5.$(basename $1) md5.tmp
+}
+
+# ---------------------------------------------------------------------
+# Initialize PVs and VGs
+
+aux prepare_vg 5 80
+
+# ---------------------------------------------------------------------
+# Common environment setup/cleanup for each sub testcases
+
+prepare_lvs_() {
+ lvcreate -l2 -n $lv1 $vg $dev1
+ lv_is_on_ $vg/$lv1 $dev1
+ lvcreate -l9 -i3 -n $lv2 $vg $dev2 $dev3 $dev4
+ lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev4
+ lvextend -l+2 $vg/$lv1 $dev2
+ lv_is_on_ $vg/$lv1 $dev1 $dev2
+ lvextend -l+2 $vg/$lv1 $dev3
+ lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev3
+ lvextend -l+2 $vg/$lv1 $dev1
+ lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev3 $dev1
+ lvcreate -l1 -n $lv3 $vg $dev2
+ lv_is_on_ $vg/$lv3 $dev2
+ save_dev_sum_ $(lvdev_ $vg $lv1)
+ save_dev_sum_ $(lvdev_ $vg $lv2)
+ save_dev_sum_ $(lvdev_ $vg $lv3)
+ lvs -a -o devices --noheadings $vg/$lv1 > ${lv1}_devs
+ lvs -a -o devices --noheadings $vg/$lv2 > ${lv2}_devs
+ lvs -a -o devices --noheadings $vg/$lv3 > ${lv3}_devs
+}
+
+lv_not_changed_() {
+ lvs -a -o devices --noheadings $1 > out
+ diff $(basename $1)_devs out
+}
+
+check_and_cleanup_lvs_() {
+ lvs -a -o+devices $vg
+ check_dev_sum_ $(lvdev_ $vg $lv1)
+ check_dev_sum_ $(lvdev_ $vg $lv2)
+ check_dev_sum_ $(lvdev_ $vg $lv3)
+ lvs -a -o name $vg > out && ! grep ^pvmove out
+ lvremove -ff $vg
+ if ! dmsetup table|not grep $vg; then
+ echo "ERROR: lvremove did leave some some mappings in DM behind!" && \
+ return 1
+ fi
+ :
+}
+
+#COMM "check environment setup/cleanup"
+prepare_lvs_
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+# pvmove tests
+
+# ---
+# filter by LV
+
+#COMM "only specified LV is moved: from pv2 to pv5 only for lv1"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv1 $dev2 $dev5
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3 $dev1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# segments in a LV
+
+#COMM "the 1st seg of 3-segs LV is moved: from pv1 of lv1 to pv4"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv1 $dev1 $dev4
+lv_is_on_ $vg/$lv1 $dev4 $dev2 $dev3 $dev4
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "the 2nd seg of 3-segs LV is moved: from pv2 of lv1 to pv4"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv1 $dev2 $dev4
+lv_is_on_ $vg/$lv1 $dev1 $dev4 $dev3 $dev1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "the 3rd seg of 3-segs LV is moved: from pv3 of lv1 to pv4"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv1 $dev3 $dev4
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev4 $dev1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# multiple LVs matching
+
+#COMM "1 out of 3 LVs is moved: from pv4 to pv5"
+prepare_lvs_
+pvmove -i1 $dev4 $dev5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev5
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "2 out of 3 LVs are moved: from pv3 to pv5"
+prepare_lvs_
+pvmove -i1 $dev3 $dev5
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev5 $dev1
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "3 out of 3 LVs are moved: from pv2 to pv5"
+prepare_lvs_
+pvmove -i1 $dev2 $dev5
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3 $dev1
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4
+lv_is_on_ $vg/$lv3 $dev5
+check_and_cleanup_lvs_
+
+# ---
+# areas of striping
+
+#COMM "move the 1st stripe: from pv2 of lv2 to pv1"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv2 $dev2 $dev1
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev1 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "move the 2nd stripe: from pv3 of lv2 to pv1"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv2 $dev3 $dev1
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev1 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "move the 3rd stripe: from pv4 of lv2 to pv1"
+prepare_lvs_
+pvmove -i1 -n $vg/$lv2 $dev4 $dev1
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev1
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# partial segment match (source segment splitted)
+
+#COMM "match to the start of segment:from pv2:0-0 to pv5"
+prepare_lvs_
+pvmove -i1 $dev2:0-0 $dev5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev5 $dev2 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "match to the middle of segment: from pv2:1-1 to pv5"
+prepare_lvs_
+pvmove -i1 $dev2:1-1 $dev5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev2 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "match to the end of segment: from pv2:2-2 to pv5"
+prepare_lvs_
+pvmove -i1 $dev2:2-2 $dev5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# destination segment splitted
+
+#COMM "no destination split: from pv2:0-2 to pv5"
+prepare_lvs_
+pvmove -i1 $dev2:0-2 $dev5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "destination split into 2: from pv2:0-2 to pv5:5-5 and pv4:5-6"
+prepare_lvs_
+pvmove -i1 --alloc anywhere $dev2:0-2 $dev5:5-5 $dev4:5-6
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev5 $dev4 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "destination split into 3: from pv2:0-2 to {pv3,4,5}:5-5"
+prepare_lvs_
+pvmove -i1 --alloc anywhere $dev2:0-2 $dev3:5-5 $dev4:5-5 $dev5:5-5
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev3 $dev4 $dev5 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# alloc policy (anywhere, contiguous) with both success and failure cases
+
+#COMM "alloc normal on same PV for source and destination: from pv3:0-2 to pv3:5-7"
+prepare_lvs_
+not pvmove -i1 $dev3:0-2 $dev3:5-7
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "alloc anywhere on same PV for source and destination: from pv3:0-2 to pv3:5-7"
+prepare_lvs_
+pvmove -i1 --alloc anywhere $dev3:0-2 $dev3:5-7
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev2 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "alloc anywhere but better area available: from pv3:0-2 to pv3:5-7 or pv5:5-6,pv4:5-5"
+prepare_lvs_
+pvmove -i1 --alloc anywhere $dev3:0-2 $dev3:5-7 $dev5:5-6 $dev4:5-5
+lv_not_changed_ $vg/$lv1
+#lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "alloc contiguous but area not available: from pv2:0-2 to pv5:5-5 and pv4:5-6"
+prepare_lvs_
+not pvmove -i1 --alloc contiguous $dev2:0-2 $dev5:5-5 $dev4:5-6
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "alloc contiguous and contiguous area available: from pv2:0-2 to pv5:0-0,pv5:3-5 and pv4:5-6"
+prepare_lvs_
+pvmove -i1 --alloc contiguous $dev2:0-2 $dev5:0-0 $dev5:3-5 $dev4:5-6
+lv_not_changed_ $vg/$lv1
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# multiple segments in a LV
+
+#COMM "multiple source LVs: from pv3 to pv5"
+prepare_lvs_
+pvmove -i1 $dev3 $dev5
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev5
+lv_is_on_ $vg/$lv2 $dev2 $dev5 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---
+# move inactive LV
+
+#COMM "move inactive LV: from pv2 to pv5"
+prepare_lvs_
+lvchange -an $vg/$lv1
+lvchange -an $vg/$lv3
+pvmove -i1 $dev2 $dev5
+lv_is_on_ $vg/$lv1 $dev1 $dev5 $dev3
+lv_is_on_ $vg/$lv2 $dev5 $dev3 $dev4
+lv_is_on_ $vg/$lv3 $dev5
+check_and_cleanup_lvs_
+
+# ---
+# other failure cases
+
+#COMM "no PEs to move: from pv3 to pv1"
+prepare_lvs_
+pvmove -i1 $dev3 $dev1
+not pvmove -i1 $dev3 $dev1
+# "(cleanup previous test)"
+lv_is_on_ $vg/$lv1 $dev1 $dev2 $dev1
+lv_is_on_ $vg/$lv2 $dev2 $dev1 $dev4
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "no space available: from pv2:0-0 to pv1:0-0"
+prepare_lvs_
+not pvmove -i1 $dev2:0-0 $dev1:0-0
+# "(cleanup previous test)"
+lv_not_changed_ $vg/$lv1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM 'same source and destination: from pv1 to pv1'
+prepare_lvs_
+not pvmove -i1 $dev1 $dev1
+#"(cleanup previous test)"
+lv_not_changed_ $vg/$lv1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+#COMM "sum of specified destination PEs is large enough, but it includes source PEs and the free PEs are not enough"
+prepare_lvs_
+not pvmove --alloc anywhere $dev1:0-2 $dev1:0-2 $dev5:0-0 2> err
+#"(cleanup previous test)"
+grep "Insufficient free space" err
+lv_not_changed_ $vg/$lv1
+lv_not_changed_ $vg/$lv2
+lv_not_changed_ $vg/$lv3
+check_and_cleanup_lvs_
+
+# ---------------------------------------------------------------------
+
+#COMM "pvmove abort"
+prepare_lvs_
+pvmove -i100 -b $dev1 $dev3
+pvmove --abort
+check_and_cleanup_lvs_
+
+#COMM "pvmove out of --metadatacopies 0 PV (bz252150)"
+vgremove -ff $vg
+pvcreate $devs
+pvcreate --metadatacopies 0 $dev1 $dev2
+vgcreate -c n $vg $devs
+lvcreate -l4 -n $lv1 $vg $dev1
+pvmove $dev1
+
+#COMM "pvmove fails activating mirror, properly restores state before pvmove"
+dmsetup create "$vg-pvmove0" --notable
+not pvmove -i 1 $dev2
+test $(dmsetup info --noheadings -c -o suspended "$vg-$lv1") = "Active"
+dmsetup remove "$vg-pvmove0"
diff --git a/test/t-pvremove-usage.sh b/test/t-pvremove-usage.sh
new file mode 100755
index 0000000..5b5700f
--- /dev/null
+++ b/test/t-pvremove-usage.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 3
+pvcreate $dev1
+pvcreate --metadatacopies 0 $dev2
+pvcreate --metadatacopies 2 $dev3
+pvremove $dev2
+
+# failing, but still removing everything what can be removed
+# is somewhat odd as default, what do we have -f for?
+pvs | not grep $dev2
+pvcreate --metadatacopies 0 $dev2
+
+# check pvremove refuses to remove pv in a vg
+vgcreate -c n $vg $dev1 $dev2
+not pvremove $dev2 $dev3
+
+for mdacp in 0 1 2; do
+ # check pvremove truly wipes the label (pvscan wont find) (---metadatacopies $mdacp)
+ pvcreate --metadatacopies $mdacp $dev3
+ pvremove $dev3
+ # try to remove agail - should fail cleanly
+ not pvremove $dev3
+ pvscan | not grep $dev3
+
+ # bz179473 refuse to wipe non-PV device without -f
+ not pvremove $dev3
+ pvremove -f $dev3
+
+ # reset setup
+ vgremove -ff $vg
+ pvcreate --metadatacopies $mdacp $dev1
+ pvcreate $dev2
+ vgcreate $vg $dev1 $dev2
+
+ # pvremove -f fails when pv in a vg (---metadatacopies $mdacp)
+ not pvremove -f $dev1
+ pvs $dev1
+
+ # pvremove -ff fails without confirmation when pv in a vg (---metadatacopies $mdacp)
+ echo n | not pvremove -ff $dev1
+
+ # pvremove -ff succeds with confirmation when pv in a vg (---metadatacopies $mdacp)
+ pvremove -ffy $dev1
+ not pvs $dev1
+
+ vgreduce --removemissing $vg
+ pvcreate --metadatacopies $mdacp $dev1
+ vgextend $vg $dev1
+
+ # pvremove -ff -y is sufficient when pv in a vg (---metadatacopies $mdacp)" '
+ echo n | pvremove -ff -y $dev1
+
+ vgreduce --removemissing $vg
+ pvcreate --metadatacopies $mdacp $dev1
+ vgextend $vg $dev1
+done
diff --git a/test/t-read-ahead.sh b/test/t-read-ahead.sh
new file mode 100755
index 0000000..6130561
--- /dev/null
+++ b/test/t-read-ahead.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# tests basic functionality of read-ahead and ra regressions
+#
+
+test_description='Test read-ahead functionality'
+
+. ./test-utils.sh
+
+
+get_lvs_() {
+ lvs --units s --nosuffix --noheadings -o $1 "$vg"/"$lv"
+}
+
+check_lvs_() {
+ case $(get_lvs_ $1) in
+ *$2) true ;;
+ *) false ;;
+ esac
+}
+
+aux prepare_vg 5
+
+#COMM "test various read ahead settings (bz450922)"
+lvcreate -n "$lv" -l 100%FREE -i5 -I256 "$vg"
+ra="$(get_lvs_ lv_kernel_read_ahead)"
+test "$(( ( $ra / 5 ) * 5 ))" -eq $ra
+lvdisplay "$vg"/"$lv"
+not lvchange -r auto "$vg"/"$lv" 2>&1 | grep auto
+check_lvs_ lv_read_ahead auto
+check_lvs_ lv_kernel_read_ahead 5120
+lvchange -r 640 "$vg/$lv"
+check_lvs_ lv_read_ahead 640
+lvremove -ff "$vg"
+
+#COMM "read ahead is properly inherited from underlying PV"
+blockdev --setra 768 $dev1
+vgscan
+lvcreate -n $lv -L4m $vg $dev1
+test $(blockdev --getra $DM_DEV_DIR/$vg/$lv) -eq 768
+lvremove -ff $vg
+
+# Check default, active/inactive values for read_ahead / kernel_read_ahead
+lvcreate -n $lv -l 50%FREE $vg
+lvchange -an $vg/$lv
+check_lv_field_ $vg/$lv lv_read_ahead auto
+check_lv_field_ $vg/$lv lv_kernel_read_ahead -1
+lvchange -r 512 $vg/$lv
+lvchange -ay $vg/$lv
+check_lv_field_ $vg/$lv lv_read_ahead 256.00k
+check_lv_field_ $vg/$lv lv_kernel_read_ahead 256.00k
+lvremove -ff $vg
diff --git a/test/t-snapshot-autoumount-dmeventd.sh b/test/t-snapshot-autoumount-dmeventd.sh
new file mode 100644
index 0000000..32659af
--- /dev/null
+++ b/test/t-snapshot-autoumount-dmeventd.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# no automatic extensions please
+LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND="
+ snapshot_autoextend_percent = 0
+ snapshot_autoextend_threshold = 100"
+
+. ./test-utils.sh
+
+which mkfs.ext2 || exit 200
+
+prepare_lvmconf
+
+aux prepare_vg 2
+aux prepare_dmeventd
+
+lvcreate -l 8 -n base $vg
+mkfs.ext2 $DM_DEV_DIR/$vg/base
+
+lvcreate -s -l 4 -n snap $vg/base
+lvchange --monitor y $vg/snap
+
+mkdir mnt
+mount $DM_DEV_DIR/$vg/snap mnt
+mount
+cat /proc/mounts | grep $vg-snap
+
+dd if=/dev/zero of=mnt/file$1 bs=1M count=17
+sync
+sleep 10 # dmeventd only checks every 10 seconds :(
+
+cat /proc/mounts | not grep $vg-snap
diff --git a/test/t-snapshot-merge.sh b/test/t-snapshot-merge.sh
new file mode 100755
index 0000000..72d96da
--- /dev/null
+++ b/test/t-snapshot-merge.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+set -xv
+
+which mkfs.ext3 || exit 200
+
+. ./test-utils.sh
+
+lvdev_()
+{
+ echo "$DM_DEV_DIR/$1/$2"
+}
+
+snap_lv_name_() {
+ echo ${1}_snap
+}
+
+setup_merge() {
+ local VG_NAME=$1
+ local LV_NAME=$2
+ local NUM_EXTRA_SNAPS="$3"
+ test -z "$NUM_EXTRA_SNAPS" && NUM_EXTRA_SNAPS=0
+ local BASE_SNAP_LV_NAME=$(snap_lv_name_ $LV_NAME)
+
+ lvcreate -n $LV_NAME -l 50%FREE $VG_NAME
+ lvcreate -s -n $BASE_SNAP_LV_NAME -l 20%FREE ${VG_NAME}/${LV_NAME}
+ mkfs.ext3 $(lvdev_ $VG_NAME $LV_NAME)
+
+ if [ $NUM_EXTRA_SNAPS -gt 0 ]; then
+ for i in `seq 1 $NUM_EXTRA_SNAPS`; do
+ lvcreate -s -n ${BASE_SNAP_LV_NAME}_${i} -l 20%FREE ${VG_NAME}/${LV_NAME}
+ done
+ fi
+}
+
+aux prepare_vg 1 100
+
+
+# test full merge of a single LV
+setup_merge $vg $lv1
+# now that snapshot LV is created: test if snapshot-merge target is available
+$(dmsetup targets | grep -q snapshot-merge) || exit 200
+lvs -a
+# make sure lvconvert --merge requires explicit LV listing
+not lvconvert --merge 2>err
+lvconvert --merge $vg/$(snap_lv_name_ $lv1)
+lvremove -f $vg/$lv1
+
+
+# test that an actively merging snapshot may not be removed
+setup_merge $vg $lv1
+lvconvert -i+100 --merge --background $vg/$(snap_lv_name_ $lv1)
+not lvremove -f $vg/$(snap_lv_name_ $lv1)
+lvremove -f $vg/$lv1
+
+
+# "onactivate merge" test
+setup_merge $vg $lv1
+lvs -a
+mkdir test_mnt
+mount $(lvdev_ $vg $lv1) test_mnt
+lvconvert --merge $vg/$(snap_lv_name_ $lv1)
+# -- refresh LV while FS is still mounted (merge must not start),
+# verify 'snapshot-origin' target is still being used
+lvchange --refresh $vg/$lv1
+umount test_mnt
+rm -r test_mnt
+dmsetup table ${vg}-${lv1} | grep -q " snapshot-origin "
+# -- refresh LV to start merge (now that FS is unmounted),
+# an active merge uses the 'snapshot-merge' target
+lvchange --refresh $vg/$lv1
+dmsetup table ${vg}-${lv1} | grep -q " snapshot-merge "
+# -- don't care if merge is still active; lvremove at this point
+# may test stopping an active merge
+lvremove -f $vg/$lv1
+
+
+# "onactivate merge" test
+# -- deactivate/remove after disallowed merge attempt, tests
+# to make sure preload of origin's metadata is _not_ performed
+setup_merge $vg $lv1
+lvs -a
+mkdir test_mnt
+mount $(lvdev_ $vg $lv1) test_mnt
+lvconvert --merge $vg/$(snap_lv_name_ $lv1)
+# -- refresh LV while FS is still mounted (merge must not start),
+# verify 'snapshot-origin' target is still being used
+lvchange --refresh $vg/$lv1
+umount test_mnt
+rm -r test_mnt
+dmsetup table ${vg}-${lv1} | grep -q " snapshot-origin "
+lvremove -f $vg/$lv1
+
+
+# test multiple snapshot merge; tests copy out that is driven by merge
+setup_merge $vg $lv1 1
+lvs -a
+lvconvert --merge $vg/$(snap_lv_name_ $lv1)
+lvremove -f $vg/$lv1
+
+
+# test merging multiple snapshots that share the same tag
+setup_merge $vg $lv1
+setup_merge $vg $lv2
+lvs -a
+lvchange --addtag this_is_a_test $vg/$(snap_lv_name_ $lv1)
+lvchange --addtag this_is_a_test $vg/$(snap_lv_name_ $lv2)
+lvconvert --merge @this_is_a_test
+lvs | not grep $(snap_lv_name_ $lv1)
+lvs | not grep $(snap_lv_name_ $lv2)
+lvremove -f $vg/$lv1
+lvremove -f $vg/$lv2
+
+# FIXME following tests would need to poll merge progress, via periodic lvs?
+# Background processes don't lend themselves to lvm testsuite...
+
+# test: onactivate merge of a single lv
+
+# test: do onactivate, deactivate the origin LV, reactivate the LV, merge should resume
+
+# test: multiple onactivate merge
+
+
+vgremove -f "$vg"
diff --git a/test/t-snapshots-of-mirrors.sh b/test/t-snapshots-of-mirrors.sh
new file mode 100644
index 0000000..fbde102
--- /dev/null
+++ b/test/t-snapshots-of-mirrors.sh
@@ -0,0 +1,44 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_vg 4
+
+# Create snapshot of a mirror origin
+lvcreate -m 1 -L 10M -n lv $vg
+lvcreate -s $vg/lv -L 10M -n snap
+
+# Down-convert (mirror -> linear) under a snapshot
+lvconvert -m0 $vg/lv
+
+# Up-convert (linear -> mirror)
+lvconvert -m2 $vg/lv
+
+# Down-convert (mirror -> mirror)
+lvconvert -m1 $vg/lv
+
+# Up-convert (mirror -> mirror) -- Not supported!
+not lvconvert -m2 $vg/lv
+
+# Log conversion (disk -> core)
+lvconvert --mirrorlog core $vg/lv
+
+# Log conversion (core -> mirrored)
+lvconvert --mirrorlog mirrored $vg/lv
+
+# Log conversion (mirrored -> core)
+lvconvert --mirrorlog core $vg/lv
+
+# Log conversion (core -> disk)
+lvconvert --mirrorlog disk $vg/lv
+
+# Clean-up
+lvremove -ff $vg
diff --git a/test/t-tags.sh b/test/t-tags.sh
new file mode 100755
index 0000000..906181c
--- /dev/null
+++ b/test/t-tags.sh
@@ -0,0 +1,74 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 5
+
+# vgcreate with --addtag
+vgcreate -c n --addtag firstvg $vg1 $dev1 $dev2
+vgcreate -c n --addtag secondvg $vg2 $dev3 $dev4
+check_vg_field_ $vg1 tags firstvg
+check_vg_field_ $vg2 tags secondvg
+vgremove -ff $vg1
+vgremove -ff $vg2
+
+# vgchange with --addtag and --deltag
+vgcreate -c n $vg1 $dev1 $dev2
+vgcreate -c n $vg2 $dev3 $dev4
+vgchange --addtag firstvgtag1 $vg1
+# adding a tag multiple times is not an error
+vgchange --addtag firstvgtag2 $vg1
+vgchange --addtag firstvgtag2 $vg1
+vgchange --addtag firstvgtag3 $vg1
+vgchange --addtag secondvgtag1 $vg2
+vgchange --addtag secondvgtag2 $vg2
+vgchange --addtag secondvgtag3 $vg2
+check_vg_field_ @firstvgtag2 tags "firstvgtag1,firstvgtag2,firstvgtag3"
+check_vg_field_ @secondvgtag1 tags "secondvgtag1,secondvgtag2,secondvgtag3"
+vgchange --deltag firstvgtag2 $vg1
+check_vg_field_ @firstvgtag1 tags "firstvgtag1,firstvgtag3"
+# deleting a tag multiple times is not an error
+vgchange --deltag firstvgtag2 $vg1
+vgchange --deltag firstvgtag1 $vg2
+vgremove -ff $vg1
+vgremove -ff $vg2
+
+# lvcreate with --addtag
+vgcreate -c n $vg1 $dev1 $dev2
+lvcreate --addtag firstlvtag1 -l 4 -n $lv1 $vg1
+lvcreate --addtag secondlvtag1 -l 4 -n $lv2 $vg1
+check_lv_field_ @firstlvtag1 tags "firstlvtag1"
+not check_lv_field_ @secondlvtag1 tags "firstlvtag1"
+check_lv_field_ $vg1/$lv2 tags "secondlvtag1"
+not check_lv_field_ $vg1/$lv1 tags "secondlvtag1"
+vgremove -ff $vg1
+
+# lvchange with --addtag and --deltag
+vgcreate -c n $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv2 $vg1
+lvchange --addtag firstlvtag1 $vg1/$lv1
+# adding a tag multiple times is not an error
+lvchange --addtag firstlvtag2 $vg1/$lv1
+lvchange --addtag firstlvtag2 $vg1/$lv1
+lvchange --addtag firstlvtag3 $vg1/$lv1
+lvchange --addtag secondlvtag1 $vg1/$lv2
+lvchange --addtag secondlvtag2 $vg1/$lv2
+lvchange --addtag secondlvtag3 $vg1/$lv2
+check_lv_field_ $vg1/$lv1 tags "firstlvtag1,firstlvtag2,firstlvtag3"
+not $(check_lv_field_ $vg1/$lv1 tags "secondlvtag1")
+check_lv_field_ $vg1/$lv2 tags "secondlvtag1,secondlvtag2,secondlvtag3"
+not $(check_lv_field_ $vg1/$lv1 tags "secondlvtag1")
+# deleting a tag multiple times is not an error
+lvchange --deltag firstlvtag2 $vg1/$lv1
+lvchange --deltag firstlvtag2 $vg1/$lv1
+check_lv_field_ $vg1/$lv1 tags "firstlvtag1,firstlvtag3"
+check_lv_field_ $vg1/$lv2 tags "secondlvtag1,secondlvtag2,secondlvtag3"
diff --git a/test/t-test-partition.sh b/test/t-test-partition.sh
new file mode 100644
index 0000000..45a0aba
--- /dev/null
+++ b/test/t-test-partition.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# Testcase for bugzilla #621173
+# excercises partition table scanning code path
+#
+
+which sfdisk || exit 200
+
+LVM_TEST_CONFIG_DEVICES="types = [\"device-mapper\", 142]"
+
+. ./test-utils.sh
+
+aux prepare_pvs 1 30
+
+pvs
+
+# create small partition table
+echo "1 2" | sfdisk $dev1
+
+pvs
diff --git a/test/t-topology-support.sh b/test/t-topology-support.sh
new file mode 100644
index 0000000..b25ed7e
--- /dev/null
+++ b/test/t-topology-support.sh
@@ -0,0 +1,104 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+which mkfs.ext3 || exit 200
+
+# Get linux minor version
+linux_minor=$(echo `uname -r` | cut -d'.' -f3 | cut -d'-' -f1)
+
+test $linux_minor -ge 31 || exit 200
+
+. ./test-utils.sh
+
+check_logical_block_size()
+{
+ local DEV_=$1
+ local LOGICAL_BS=$2
+ # Verify logical_block_size - requires Linux >= 2.6.31
+ SYSFS_LOGICAL_BLOCK_SIZE=`echo /sys/block/$(basename $DEV_)/queue/logical_block_size`
+ if [ -f "$SYSFS_LOGICAL_BLOCK_SIZE" ] ; then
+ ACTUAL_LOGICAL_BLOCK_SIZE=`cat $SYSFS_LOGICAL_BLOCK_SIZE`
+ test $ACTUAL_LOGICAL_BLOCK_SIZE = $LOGICAL_BS
+ fi
+}
+
+lvdev_()
+{
+ echo "$DM_DEV_DIR/$1/$2"
+}
+
+test_snapshot_mount()
+{
+ lvcreate -L 16M -n $lv1 $vg $dev1
+ mkfs.ext3 $(lvdev_ $vg $lv1)
+ mkdir test_mnt
+ mount $(lvdev_ $vg $lv1) test_mnt
+ lvcreate -L 16M -n $lv2 -s $vg/$lv1
+ umount test_mnt
+ # mount the origin
+ mount $(lvdev_ $vg $lv1) test_mnt
+ umount test_mnt
+ # mount the snapshot
+ mount $(lvdev_ $vg $lv2) test_mnt
+ umount test_mnt
+ rm -r test_mnt
+ vgchange -an $vg
+ lvremove -f $vg/$lv2
+ lvremove -f $vg/$lv1
+}
+
+# FIXME add more topology-specific tests and validation (striped LVs, etc)
+
+NUM_DEVS=1
+PER_DEV_SIZE=34
+DEV_SIZE=$(($NUM_DEVS*$PER_DEV_SIZE))
+
+# ---------------------------------------------
+# Create "desktop-class" 4K drive
+# (logical_block_size=512, physical_block_size=4096, alignment_offset=0):
+LOGICAL_BLOCK_SIZE=512
+prepare_scsi_debug_dev $DEV_SIZE \
+ sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=3
+check_logical_block_size $SCSI_DEBUG_DEV $LOGICAL_BLOCK_SIZE
+
+aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE
+vgcreate -c n $vg $devs
+test_snapshot_mount
+vgremove $vg
+
+cleanup_scsi_debug_dev
+
+# ---------------------------------------------
+# Create "desktop-class" 4K drive w/ 63-sector DOS partition compensation
+# (logical_block_size=512, physical_block_size=4096, alignment_offset=3584):
+LOGICAL_BLOCK_SIZE=512
+prepare_scsi_debug_dev $DEV_SIZE \
+ sector_size=$LOGICAL_BLOCK_SIZE physblk_exp=3 lowest_aligned=7
+check_logical_block_size $SCSI_DEBUG_DEV $LOGICAL_BLOCK_SIZE
+
+aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE
+vgcreate -c n $vg $devs
+test_snapshot_mount
+vgremove $vg
+
+cleanup_scsi_debug_dev
+
+# ---------------------------------------------
+# Create "enterprise-class" 4K drive
+# (logical_block_size=4096, physical_block_size=4096, alignment_offset=0):
+LOGICAL_BLOCK_SIZE=4096
+prepare_scsi_debug_dev $DEV_SIZE \
+ sector_size=$LOGICAL_BLOCK_SIZE
+check_logical_block_size $SCSI_DEBUG_DEV $LOGICAL_BLOCK_SIZE
+
+aux prepare_pvs $NUM_DEVS $PER_DEV_SIZE
+vgcreate -c n $vg $devs
+test_snapshot_mount
+vgremove $vg
diff --git a/test/t-unknown-segment.sh b/test/t-unknown-segment.sh
new file mode 100644
index 0000000..74a2710
--- /dev/null
+++ b/test/t-unknown-segment.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 4
+
+lvcreate -l 1 -n $lv1 $vg
+lvcreate -l 2 -m 1 -n $lv2 $vg
+
+vgcfgbackup -f bak0 $vg
+sed -e 's,striped,unstriped,;s,mirror,unmirror,' -i.orig bak0
+vgcfgrestore -f bak0 $vg
+
+# we have on-disk metadata with unknown segments now
+not lvchange -a y $vg/$lv1 # check that activation is refused
+
+vgcfgbackup -f bak1 $vg
+cat bak1
+sed -e 's,unstriped,striped,;s,unmirror,mirror,' -i.orig bak1
+vgcfgrestore -f bak1 $vg
+vgcfgbackup -f bak2 $vg
+
+egrep -v 'description|seqno|creation_time|Generated' < bak0.orig > a
+egrep -v 'description|seqno|creation_time|Generated' < bak2 > b
+diff -u a b
diff --git a/test/t-unlost-pv.sh b/test/t-unlost-pv.sh
new file mode 100644
index 0000000..7a120fb
--- /dev/null
+++ b/test/t-unlost-pv.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_vg 3
+
+lvcreate -m 1 -l 1 -n mirror $vg
+lvchange -a n $vg/mirror
+
+check() {
+vgscan 2>&1 | tee vgscan.out
+grep "Inconsistent metadata found for VG $vg" vgscan.out
+vgscan 2>&1 | tee vgscan.out
+not grep "Inconsistent metadata found for VG $vg" vgscan.out
+}
+
+# try orphaning a missing PV (bz45867)
+disable_dev $dev1
+vgreduce --removemissing --force $vg
+enable_dev $dev1
+check
+
+# try to just change metadata; we expect the new version (with MISSING_PV set
+# on the reappeared volume) to be written out to the previously missing PV
+vgextend $vg $dev1
+disable_dev $dev1
+lvremove $vg/mirror
+enable_dev $dev1
+check
diff --git a/test/t-vgcfgbackup-usage.sh b/test/t-vgcfgbackup-usage.sh
new file mode 100644
index 0000000..72b37bb
--- /dev/null
+++ b/test/t-vgcfgbackup-usage.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_pvs 4
+
+# vgcfgbackup handles similar VG names (bz458941)
+vg1=${PREFIX}vg00
+vg2=${PREFIX}vg01
+vgcreate $vg1 $dev1
+vgcreate $vg2 $dev2
+vgcfgbackup -f $TESTDIR/bak-%s >out
+grep "Volume group \"$vg1\" successfully backed up." out
+grep "Volume group \"$vg2\" successfully backed up." out
+vgremove -ff $vg1
+vgremove -ff $vg2
+
+# vgcfgbackup correctly stores metadata with missing PVs
+# and vgcfgrestore able to restore them when device reappears
+pv1_uuid=$(pvs --noheadings -o pv_uuid $dev1)
+pv2_uuid=$(pvs --noheadings -o pv_uuid $dev2)
+vgcreate $vg $devs
+lvcreate -l1 -n $lv1 $vg $dev1
+lvcreate -l1 -n $lv2 $vg $dev2
+lvcreate -l1 -n $lv3 $vg $dev3
+vgchange -a n $vg
+pvcreate -ff -y $dev1
+pvcreate -ff -y $dev2
+vgcfgbackup -f "$(pwd)/backup.$$" $vg
+sed 's/flags = \[\"MISSING\"\]/flags = \[\]/' "$(pwd)/backup.$$" > "$(pwd)/backup.$$1"
+pvcreate -ff -y --norestorefile -u $pv1_uuid $dev1
+pvcreate -ff -y --norestorefile -u $pv2_uuid $dev2
+vgcfgrestore -f "$(pwd)/backup.$$1" $vg
+vgremove -ff $vg
+
+# vgcfgbackup correctly stores metadata LVM1 with missing PVs
+# FIXME: clvmd seems to have problem with metadata format change here
+# fix it and remove this vgscan
+vgscan
+pvcreate -M1 $devs
+vgcreate -M1 -c n $vg $devs
+lvcreate -l1 -n $lv1 $vg $dev1
+pvremove -ff -y $dev2
+not lvcreate -l1 -n $lv1 $vg $dev3
+vgcfgbackup -f "$(pwd)/backup.$$" $vg
diff --git a/test/t-vgchange-maxlv.sh b/test/t-vgchange-maxlv.sh
new file mode 100644
index 0000000..0148315
--- /dev/null
+++ b/test/t-vgchange-maxlv.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_dmeventd
+aux prepare_pvs 3
+
+vgcreate -c n -l 2 $vg $dev1 $dev2 $dev3
+lvcreate -n one -l 1 $vg
+lvcreate -n two -l 1 $vg
+not lvcreate -n three -l 1 $vg
+vgchange -an $vg
+vgremove -ff $vg
+
+vgcreate -c n -l 3 $vg $dev1 $dev2 $dev3
+lvcreate -n one -l 1 $vg
+lvcreate -n snap -s -l 1 $vg/one
+lvcreate -n two -l 1 $vg
+not lvcreate -n three -l 1 $vg
+vgchange --monitor y $vg
+vgchange -an $vg 2>&1 | tee vgchange.out
+not grep "event server" vgchange.out
diff --git a/test/t-vgchange-usage.sh b/test/t-vgchange-usage.sh
new file mode 100644
index 0000000..4baaab3
--- /dev/null
+++ b/test/t-vgchange-usage.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='Exercise some vgchange diagnostics'
+
+. ./test-utils.sh
+
+aux prepare_pvs 3
+pvcreate --metadatacopies 0 $dev1
+vgcreate $vg $devs
+
+vgdisplay $vg
+
+# vgchange -p MaxPhysicalVolumes (bz202232)
+aux check_vg_field_ $vg max_pv 0
+vgchange -p 128 $vg
+aux check_vg_field_ $vg max_pv 128
+
+pv_count=$(get_vg_field $vg pv_count)
+not vgchange -p 2 $vg 2>err
+grep "MaxPhysicalVolumes is less than the current number $pv_count of PVs for" err
+aux check_vg_field_ $vg max_pv 128
+
+# vgchange -l MaxLogicalVolumes
+aux check_vg_field_ $vg max_lv 0
+vgchange -l 128 $vg
+aux check_vg_field_ $vg max_lv 128
+
+lvcreate -l4 -n$lv1 $vg
+lvcreate -l4 -n$lv2 $vg
+
+lv_count=$(get_vg_field $vg lv_count)
+not vgchange -l 1 $vg 2>err
+grep "MaxLogicalVolume is less than the current number $lv_count of LVs for" err
+aux check_vg_field_ $vg max_lv 128
+
diff --git a/test/t-vgcreate-usage.sh b/test/t-vgcreate-usage.sh
new file mode 100755
index 0000000..9f1cd82
--- /dev/null
+++ b/test/t-vgcreate-usage.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='Exercise some vgcreate diagnostics'
+
+. ./test-utils.sh
+
+aux prepare_devs 3
+pvcreate $dev1 $dev2
+pvcreate --metadatacopies 0 $dev3
+
+vg=${PREFIX}vg
+
+#COMM 'vgcreate accepts 8.00m physicalextentsize for VG'
+vgcreate -c n $vg --physicalextentsize 8.00m $dev1 $dev2
+check_vg_field_ $vg vg_extent_size 8.00m
+vgremove $vg
+# try vgck and to remove it again - should fail (but not segfault)
+not vgremove $vg
+not vgck $vg
+
+#COMM 'vgcreate accepts smaller (128) maxlogicalvolumes for VG'
+vgcreate -c n $vg --maxlogicalvolumes 128 $dev1 $dev2
+check_vg_field_ $vg max_lv 128
+vgremove $vg
+
+#COMM 'vgcreate accepts smaller (128) maxphysicalvolumes for VG'
+vgcreate -c n $vg --maxphysicalvolumes 128 $dev1 $dev2
+check_vg_field_ $vg max_pv 128
+vgremove $vg
+
+#COMM 'vgcreate rejects a zero physical extent size'
+not vgcreate -c n --physicalextentsize 0 $vg $dev1 $dev2 2>err
+grep "^ Physical extent size may not be zero\$" err
+
+#COMM 'vgcreate rejects "inherit" allocation policy'
+not vgcreate -c n --alloc inherit $vg $dev1 $dev2 2>err
+grep "^ Volume Group allocation policy cannot inherit from anything\$" err
+
+#COMM 'vgcreate rejects vgname "."'
+vginvalid=.;
+not vgcreate -c n $vginvalid $dev1 $dev2 2>err
+grep "New volume group name \"$vginvalid\" is invalid\$" err
+
+#COMM 'vgcreate rejects vgname greater than 128 characters'
+vginvalid=thisnameisridiculouslylongtotestvalidationcodecheckingmaximumsizethisiswhathappenswhenprogrammersgetboredandorarenotcreativedonttrythisathome
+not vgcreate -c n $vginvalid $dev1 $dev2 2>err
+grep "New volume group name \"$vginvalid\" is invalid\$" err
+
+#COMM 'vgcreate rejects already existing vgname "/tmp/$vg"'
+#touch /tmp/$vg
+#not vgcreate $vg $dev1 $dev2 2>err
+#grep "New volume group name \"$vg\" is invalid\$" err
+
+#COMM "vgcreate rejects repeated invocation (run 2 times) (bz178216)"
+vgcreate -c n $vg $dev1 $dev2
+not vgcreate -c n $vg $dev1 $dev2
+vgremove -ff $vg
+
+#COMM 'vgcreate rejects MaxLogicalVolumes > 255'
+not vgcreate -c n --metadatatype 1 --maxlogicalvolumes 1024 $vg $dev1 $dev2 2>err
+grep "^ Number of volumes may not exceed 255\$" err
+
+#COMM "vgcreate fails when the only pv has --metadatacopies 0"
+not vgcreate -c n $vg $dev3
+
+# Test default (4MB) vg_extent_size as well as limits of extent_size
+not vgcreate -c n --physicalextentsize 0k $vg $dev1 $dev2
+vgcreate -c n --physicalextentsize 1k $vg $dev1 $dev2
+check_vg_field_ $vg vg_extent_size 1.00k
+vgremove -ff $vg
+not vgcreate -c n --physicalextentsize 3K $vg $dev1 $dev2
+not vgcreate -c n --physicalextentsize 1024t $vg $dev1 $dev2
+#not vgcreate --physicalextentsize 1T $vg $dev1 $dev2
+# FIXME: vgcreate allows physicalextentsize larger than pv size!
+
+# Test default max_lv, max_pv, extent_size, alloc_policy, clustered
+vgcreate -c n $vg $dev1 $dev2
+check_vg_field_ $vg vg_extent_size 4.00m
+check_vg_field_ $vg max_lv 0
+check_vg_field_ $vg max_pv 0
+check_vg_field_ $vg vg_attr "wz--n-"
+vgremove -ff $vg
+
+# Implicit pvcreate tests, test pvcreate options on vgcreate
+# --force, --yes, --metadata{size|copies|type}, --zero
+# --dataalignment[offset]
+pvremove $dev1 $dev2
+vgcreate -c n --force --yes --zero y $vg $dev1 $dev2
+vgremove -f $vg
+pvremove -f $dev1
+
+for i in 0 1 2 3
+do
+# vgcreate (lvm2) succeeds writing LVM label at sector $i
+ vgcreate -c n --labelsector $i $vg $dev1
+ dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE;
+ vgremove -f $vg
+ pvremove -f $dev1
+done
+
+# pvmetadatacopies
+for i in 1 2
+do
+ vgcreate -c n --pvmetadatacopies $i $vg $dev1
+ check_pv_field_ $dev1 pv_mda_count $i
+ vgremove -f $vg
+ pvremove -f $dev1
+done
+not vgcreate -c n --pvmetadatacopies 0 $vg $dev1
+pvcreate --metadatacopies 1 $dev2
+vgcreate -c n --pvmetadatacopies 0 $vg $dev1 $dev2
+check_pv_field_ $dev1 pv_mda_count 0
+check_pv_field_ $dev2 pv_mda_count 1
+vgremove -f $vg
+pvremove -f $dev1
+
+# metadatasize, dataalignment, dataalignmentoffset
+#COMM 'pvcreate sets data offset next to mda area'
+vgcreate -c n --metadatasize 100k --dataalignment 100k $vg $dev1
+check_pv_field_ $dev1 pe_start 200.00k
+vgremove -f $vg
+pvremove -f $dev1
+
+# data area is aligned to 1M by default,
+# data area start is shifted by the specified alignment_offset
+pv_align="1052160B" # 1048576 + (7*512)
+vgcreate -c n --metadatasize 128k --dataalignmentoffset 7s $vg $dev1
+check_pv_field_ $dev1 pe_start $pv_align "--units b"
+vgremove -f $vg
+pvremove -f $dev1
+
+# metadatatype
+for i in 1 2
+do
+ vgcreate -c n -M $i $vg $dev1
+ check_vg_field_ $vg vg_fmt lvm$i
+ vgremove -f $vg
+ pvremove -f $dev1
+done
+
+# vgcreate fails if pv belongs to existing vg
+vgcreate -c n $vg1 $dev1 $dev2
+not vgcreate $vg2 $dev2
+vgremove -f $vg1
+pvremove -f $dev1 $dev2
+
+# all PVs exist in the VG after created
+pvcreate $dev1
+vgcreate -c n $vg1 $dev1 $dev2 $dev3
+check_pv_field_ $dev1 vg_name $vg1
+check_pv_field_ $dev2 vg_name $vg1
+check_pv_field_ $dev3 vg_name $vg1
+vgremove -f $vg1
+pvremove -f $dev1 $dev2 $dev3
diff --git a/test/t-vgextend-restoremissing.sh b/test/t-vgextend-restoremissing.sh
new file mode 100644
index 0000000..87ff954
--- /dev/null
+++ b/test/t-vgextend-restoremissing.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+
+aux prepare_vg 3
+lvcreate -m 1 -l 1 -n mirror $vg
+lvchange -a n $vg/mirror
+lvcreate -l 1 -n lv1 $vg $dev1
+
+# try to just change metadata; we expect the new version (with MISSING_PV set
+# on the reappeared volume) to be written out to the previously missing PV
+disable_dev $dev1
+lvremove $vg/mirror
+enable_dev $dev1
+not vgck $vg 2>&1 | tee log
+grep "missing 1 physical volume" log
+not lvcreate -m 1 -l 1 -n mirror $vg # write operations fail
+vgextend --restore $vg $dev1 # restore the missing device
+vgck $vg
+lvcreate -m 1 -l 1 -n mirror $vg
diff --git a/test/t-vgextend-usage.sh b/test/t-vgextend-usage.sh
new file mode 100644
index 0000000..eda8904
--- /dev/null
+++ b/test/t-vgextend-usage.sh
@@ -0,0 +1,129 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# Exercise various vgextend commands
+#
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+for mdatype in 1 2
+do
+
+# Explicit pvcreate
+pvcreate -M$mdatype $dev1 $dev2 $dev3 $dev4 $dev5
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgextend $vg1 $dev3 $dev4 $dev5
+vgremove -ff $vg1
+
+# Implicit pvcreate
+pvremove $dev1 $dev2 $dev3 $dev4 $dev5
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgextend -M$mdatype $vg1 $dev3 $dev4 $dev5
+vgremove -ff $vg1
+pvremove $dev1 $dev2 $dev3 $dev4 $dev5
+
+done
+
+# Implicit pvcreate tests, test pvcreate options on vgcreate
+# --force, --yes, --metadata{size|copies|type}, --zero
+# --dataalignment[offset]
+vgcreate $vg $dev2
+vgextend --force --yes --zero y $vg $dev1
+vgreduce $vg $dev1
+pvremove -f $dev1
+
+for i in 0 1 2 3
+do
+# vgcreate (lvm2) succeeds writing LVM label at sector $i
+ vgextend --labelsector $i $vg $dev1
+ dd if=$dev1 bs=512 skip=$i count=1 2>/dev/null | strings | grep -q LABELONE;
+ vgreduce $vg $dev1
+ pvremove -f $dev1
+done
+
+# pvmetadatacopies
+for i in 0 1 2
+do
+ vgextend --pvmetadatacopies $i $vg $dev1
+ check_pv_field_ $dev1 pv_mda_count $i
+ vgreduce $vg $dev1
+ pvremove -f $dev1
+done
+
+# metadatasize, dataalignment, dataalignmentoffset
+#COMM 'pvcreate sets data offset next to mda area'
+vgextend --metadatasize 100k --dataalignment 100k $vg $dev1
+check_pv_field_ $dev1 pe_start 200.00k
+vgreduce $vg $dev1
+pvremove -f $dev1
+
+# data area is aligned to 1M by default,
+# data area start is shifted by the specified alignment_offset
+pv_align="1052160B" # 1048576 + (7*512)
+vgextend --metadatasize 128k --dataalignmentoffset 7s $vg $dev1
+check_pv_field_ $dev1 pe_start $pv_align "--units b"
+vgremove -f $vg
+pvremove -f $dev1
+
+# vgextend fails if pv belongs to existing vg
+vgcreate $vg1 $dev1 $dev3
+vgcreate $vg2 $dev2
+not vgextend $vg2 $dev3
+vgremove -f $vg1
+vgremove -f $vg2
+pvremove -f $dev1 $dev2 $dev3
+
+#vgextend fails if vg is not resizeable
+vgcreate $vg1 $dev1 $dev2
+vgchange --resizeable n $vg1
+not vgextend $vg1 $dev3
+vgremove -f $vg1
+pvremove -f $dev1 $dev2
+
+# all PVs exist in the VG after extended
+pvcreate $dev1
+vgcreate $vg1 $dev2
+vgextend $vg1 $dev1 $dev3
+check_pv_field_ $dev1 vg_name $vg1
+check_pv_field_ $dev2 vg_name $vg1
+check_pv_field_ $dev3 vg_name $vg1
+vgremove -f $vg1
+pvremove -f $dev1 $dev2 $dev3
+
+echo test vgextend --metadataignore
+for mdacp in 1 2; do
+for ignore in y n; do
+ echo vgextend --metadataignore has proper mda_count and mda_used_count
+ vgcreate $vg $dev3
+ vgextend --metadataignore $ignore --pvmetadatacopies $mdacp $vg $dev1 $dev2
+ check_pv_field_ $dev1 pv_mda_count $mdacp
+ check_pv_field_ $dev2 pv_mda_count $mdacp
+ if [ $ignore = y ]; then
+ check_pv_field_ $dev1 pv_mda_used_count 0
+ check_pv_field_ $dev2 pv_mda_used_count 0
+ else
+ check_pv_field_ $dev1 pv_mda_used_count $mdacp
+ check_pv_field_ $dev2 pv_mda_used_count $mdacp
+ fi
+ echo vg has proper vg_mda_count and vg_mda_used_count
+ check_vg_field_ $vg vg_mda_count $(($mdacp * 2 + 1))
+ if [ $ignore = y ]; then
+ check_vg_field_ $vg vg_mda_used_count 1
+ else
+ check_vg_field_ $vg vg_mda_used_count $(($mdacp * 2 + 1))
+ fi
+ check_vg_field_ $vg vg_mda_copies unmanaged
+ vgremove $vg
+ pvremove -ff $dev1 $dev2 $dev3
+done
+done
diff --git a/test/t-vgmerge-operation.sh b/test/t-vgmerge-operation.sh
new file mode 100755
index 0000000..3c7121b
--- /dev/null
+++ b/test/t-vgmerge-operation.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+test_description='Test vgmerge operation'
+
+. ./test-utils.sh
+
+aux prepare_pvs 4 64
+
+# 'vgmerge succeeds with single linear LV in source VG'
+vgcreate -c n $vg1 $dev1 $dev2
+vgcreate -c n $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1 $dev1
+vgchange -an $vg1
+vg_validate_pvlv_counts_ $vg1 2 1 0
+vg_validate_pvlv_counts_ $vg2 2 0 0
+vgmerge $vg2 $vg1
+vg_validate_pvlv_counts_ $vg2 4 1 0
+vgremove -f $vg2
+
+# 'vgmerge succeeds with single linear LV in source and destination VG'
+vgcreate -c n $vg1 $dev1 $dev2
+vgcreate -c n $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv2 $vg2
+vgchange -an $vg1
+vgchange -an $vg2
+vg_validate_pvlv_counts_ $vg1 2 1 0
+vg_validate_pvlv_counts_ $vg2 2 1 0
+vgmerge $vg2 $vg1
+vg_validate_pvlv_counts_ $vg2 4 2 0
+vgremove -f $vg2
+
+# 'vgmerge succeeds with linear LV + snapshots in source VG'
+vgcreate -c n $vg1 $dev1 $dev2
+vgcreate -c n $vg2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 $vg1
+lvcreate -l 4 -s -n $lv2 $vg1/$lv1
+vgchange -an $vg1
+vg_validate_pvlv_counts_ $vg1 2 2 1
+vg_validate_pvlv_counts_ $vg2 2 0 0
+vgmerge $vg2 $vg1
+vg_validate_pvlv_counts_ $vg2 4 2 1
+lvremove -f $vg2/$lv2
+vgremove -f $vg2
+
+# 'vgmerge succeeds with mirrored LV in source VG'
+vgcreate -c n $vg1 $dev1 $dev2 $dev3
+vgcreate -c n $vg2 $dev4
+lvcreate -l 4 -n $lv1 -m1 $vg1
+vgchange -an $vg1
+vg_validate_pvlv_counts_ $vg1 3 1 0
+vg_validate_pvlv_counts_ $vg2 1 0 0
+vgmerge $vg2 $vg1
+vg_validate_pvlv_counts_ $vg2 4 1 0
+lvremove -f $vg2/$lv1
+vgremove -f $vg2
+
+# 'vgmerge rejects LV name collision'
+vgcreate -c n $vg1 $dev1 $dev2
+vgcreate -c n $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv1 $vg2
+vgchange -an $vg1
+aux vg_validate_pvlv_counts_ $vg1 2 1 0
+aux vg_validate_pvlv_counts_ $vg2 2 1 0
+not vgmerge $vg2 $vg1 2>err
+grep "Duplicate logical volume name \"$lv1\" in \"$vg2\" and \"$vg1" err
+aux vg_validate_pvlv_counts_ $vg1 2 1 0
+aux vg_validate_pvlv_counts_ $vg2 2 1 0
+vgremove -f $vg1
+vgremove -f $vg2
+
diff --git a/test/t-vgmerge-usage.sh b/test/t-vgmerge-usage.sh
new file mode 100755
index 0000000..4be9e1e
--- /dev/null
+++ b/test/t-vgmerge-usage.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# 'Test vgmerge command options for validity'
+
+. ./test-utils.sh
+
+aux prepare_pvs 4
+
+# 'vgmerge normal operation'
+# ensure ordering does not matter
+vgcreate $vg1 $dev1 $dev2
+vgcreate $vg2 $dev3 $dev4
+vgmerge $vg1 $vg2
+vgremove $vg1
+vgcreate -c n $vg2 $dev1 $dev2
+vgcreate -c n $vg1 $dev3 $dev4
+vgmerge $vg2 $vg1
+vgremove $vg2
+
+# 'vgmerge rejects duplicate vg name'
+vgcreate $vg1 $dev1 $dev2
+vgcreate $vg2 $dev3 $dev4
+not vgmerge $vg1 $vg1 2>err
+grep "^ Duplicate volume group name \"$vg1\"\$" err
+vgremove $vg2
+vgremove $vg1
+
+# 'vgmerge rejects vgs with incompatible extent_size'
+vgcreate --physicalextentsize 4M $vg1 $dev1 $dev2
+vgcreate --physicalextentsize 8M $vg2 $dev3 $dev4
+not vgmerge $vg1 $vg2 2>err
+grep "^ Extent sizes differ" err
+vgremove $vg2
+vgremove $vg1
+
+# 'vgmerge rejects vgmerge because max_pv is exceeded'
+vgcreate --maxphysicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate --maxphysicalvolumes 2 $vg2 $dev3 $dev4
+not vgmerge $vg1 $vg2 2>err
+grep "^ Maximum number of physical volumes (2) exceeded" err
+vgremove $vg2
+vgremove $vg1
+
+# 'vgmerge rejects vg with active lv'
+vgcreate $vg1 $dev1 $dev2
+vgcreate $vg2 $dev3 $dev4
+lvcreate -l 4 -n lv1 $vg2
+not vgmerge $vg1 $vg2 2>err
+grep "^ Logical volumes in \"$vg2\" must be inactive\$" err
+vgremove -f $vg2
+vgremove -f $vg1
+
+# 'vgmerge rejects vgmerge because max_lv is exceeded'
+vgcreate --maxlogicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate --maxlogicalvolumes 2 $vg2 $dev3 $dev4
+lvcreate -l 4 -n lv1 $vg1
+lvcreate -l 4 -n lv2 $vg1
+lvcreate -l 4 -n lv3 $vg2
+vgchange -an $vg1
+vgchange -an $vg2
+not vgmerge $vg1 $vg2 2>err
+grep "^ Maximum number of logical volumes (2) exceeded" err
+vgremove -f $vg2
+vgremove -f $vg1
diff --git a/test/t-vgreduce-usage.sh b/test/t-vgreduce-usage.sh
new file mode 100755
index 0000000..6a09cfa
--- /dev/null
+++ b/test/t-vgreduce-usage.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+
+for mdatype in 1 2
+do
+ # setup PVs
+ pvcreate -M$mdatype $dev1 $dev2
+
+ # (lvm$mdatype) vgreduce removes only the specified pv from vg (bz427382)" '
+ vgcreate -c n -M$mdatype $vg1 $dev1 $dev2
+ vgreduce $vg1 $dev1
+ check_pv_field_ $dev2 vg_name $vg1
+ vgremove -f $vg1
+
+ # (lvm$mdatype) vgreduce rejects removing the last pv (--all)
+ vgcreate -c n -M$mdatype $vg1 $dev1 $dev2
+ not vgreduce --all $vg1
+ vgremove -f $vg1
+
+ # (lvm$mdatype) vgreduce rejects removing the last pv
+ vgcreate -c n -M$mdatype $vg1 $dev1 $dev2
+ not vgreduce $vg1 $dev1 $dev2
+ vgremove -f $vg1
+
+ pvremove -ff $dev1 $dev2
+done
+
+mdatype=2 # we only expect the following to work for lvm2 metadata
+
+# (lvm$mdatype) setup PVs (--metadatacopies 0)
+pvcreate -M$mdatype $dev1 $dev2
+pvcreate --metadatacopies 0 -M$mdatype $dev3 $dev4
+
+# (lvm$mdatype) vgreduce rejects removing pv with the last mda copy (bz247448)
+vgcreate -c n -M$mdatype $vg1 $dev1 $dev3
+not vgreduce $vg1 $dev1
+vgremove -f $vg1
+
+#COMM "(lvm$mdatype) vgreduce --removemissing --force repares to linear (bz221921)"
+# (lvm$mdatype) setup: create mirror & damage one pv
+vgcreate -c n -M$mdatype $vg1 $dev1 $dev2 $dev3
+lvcreate -n $lv1 -m1 -l 4 $vg1
+lvcreate -n $lv2 -l 4 $vg1 $dev2
+lvcreate -n $lv3 -l 4 $vg1 $dev3
+vgchange -an $vg1
+aux disable_dev $dev1
+# (lvm$mdatype) vgreduce --removemissing --force repares to linear
+vgreduce --removemissing --force $vg1
+check_lv_field_ $vg1/$lv1 segtype linear
+vg_validate_pvlv_counts_ $vg1 2 3 0
+# cleanup
+aux enable_dev $dev1
+vgremove -ff $vg1
+
+#COMM "vgreduce rejects --removemissing --mirrorsonly --force when nonmirror lv lost too"
+# (lvm$mdatype) setup: create mirror + linear lvs
+vgcreate -c n -M$mdatype $vg1 $devs
+lvcreate -n $lv2 -l 4 $vg1
+lvcreate -m1 -n $lv1 -l 4 $vg1 $dev1 $dev2 $dev3
+lvcreate -n $lv3 -l 4 $vg1 $dev3
+pvs --segments -o +lv_name # for record only
+# (lvm$mdatype) setup: damage one pv
+vgchange -an $vg1
+aux disable_dev $dev1
+#pvcreate -ff -y $dev1
+# vgreduce rejects --removemissing --mirrorsonly --force when nonmirror lv lost too
+not vgreduce -c n --removemissing --mirrorsonly --force $vg1
+
+aux enable_dev $dev1
+
+pvs -P # for record
+lvs -P # for record
+vgs -P # for record
diff --git a/test/t-vgrename-usage.sh b/test/t-vgrename-usage.sh
new file mode 100755
index 0000000..61e861c
--- /dev/null
+++ b/test/t-vgrename-usage.sh
@@ -0,0 +1,41 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+aux prepare_devs 4
+pvcreate $dev1 $dev2
+pvcreate --metadatacopies 0 $dev3 $dev4
+
+# vgrename normal operation - rename vg1 to vg2
+# vgrename normal operation - rename vg2 to vg1
+# ensure name ordering does not matter
+vgcreate $vg1 $dev1 $dev2
+vgrename $vg1 $vg2
+check_vg_field_ $vg2 vg_name $vg2
+vgrename $vg2 $vg1
+check_vg_field_ $vg1 vg_name $vg1
+vgremove $vg1
+
+# vgrename by uuid (bz231187)
+vgcreate $vg1 $dev1 $dev3
+UUID=$(vgs --noheading -o vg_uuid $vg1)
+check_vg_field_ $vg1 vg_uuid $UUID
+vgrename $UUID $vg2
+check_vg_field_ $vg2 vg_name $vg2
+vgremove $vg2
+
+# vgrename fails - new vg already exists
+vgcreate $vg1 $dev1
+vgcreate $vg2 $dev2
+not vgrename $vg1 $vg2
+vgremove $vg1
+vgremove $vg2
+
diff --git a/test/t-vgsplit-operation.sh b/test/t-vgsplit-operation.sh
new file mode 100755
index 0000000..9a46a8e
--- /dev/null
+++ b/test/t-vgsplit-operation.sh
@@ -0,0 +1,290 @@
+#!/bin/sh
+# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Test vgsplit operation, including different LV types
+
+. ./test-utils.sh
+
+COMM() {
+ LAST_TEST="$@"
+}
+
+prepare_pvs 5 258
+# FIXME: paramaterize lvm1 vs lvm2 metadata; most of these tests should run
+# fine with lvm1 metadata as well; for now, just add disks 5 and 6 as lvm1
+# metadata
+
+#
+# vgsplit can be done into a new or existing VG
+#
+for i in new existing
+do
+ #
+ # We can have PVs or LVs on the cmdline
+ #
+ for j in PV LV
+ do
+COMM "vgsplit correctly splits single linear LV into $i VG ($j args)"
+ vgcreate $vg1 $dev1 $dev2
+ if [ $i = existing ]; then
+ vgcreate $vg2 $dev3 $dev4
+ fi
+ lvcreate -l 4 -n $lv1 $vg1 $dev1
+ vgchange -an $vg1
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev1
+ else
+ vgsplit -n $lv1 $vg1 $vg2
+ fi
+ vg_validate_pvlv_counts_ $vg1 1 0 0
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg2 3 1 0
+ else
+ aux vg_validate_pvlv_counts_ $vg2 1 1 0
+ fi
+ lvremove -f $vg2/$lv1
+ vgremove -f $vg2
+ vgremove -f $vg1
+
+COMM "vgsplit correctly splits single striped LV into $i VG ($j args)"
+ vgcreate $vg1 $dev1 $dev2
+ if [ $i = existing ]; then
+ vgcreate $vg2 $dev3 $dev4
+ fi
+ lvcreate -l 4 -i 2 -n $lv1 $vg1 $dev1 $dev2
+ vgchange -an $vg1
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev1 $dev2
+ else
+ vgsplit -n $lv1 $vg1 $vg2
+ fi
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg2 4 1 0
+ else
+ aux vg_validate_pvlv_counts_ $vg2 2 1 0
+ fi
+ lvremove -f $vg2/$lv1
+ vgremove -f $vg2
+
+COMM "vgsplit correctly splits mirror LV into $i VG ($j args)"
+ vgcreate -c n $vg1 $dev1 $dev2 $dev3
+ if [ $i = existing ]; then
+ vgcreate -c n $vg2 $dev4
+ fi
+ lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3
+ vgchange -an $vg1
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev1 $dev2 $dev3
+ else
+ vgsplit -n $lv1 $vg1 $vg2
+ fi
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg2 4 1 0
+ else
+ aux vg_validate_pvlv_counts_ $vg2 3 1 0
+ fi
+ lvremove -f $vg2/$lv1
+ vgremove -f $vg2
+
+COMM "vgsplit correctly splits origin and snapshot LV into $i VG ($j args)"
+ vgcreate -c n $vg1 $dev1 $dev2
+ if [ $i = existing ]; then
+ vgcreate -c n $vg2 $dev3 $dev4
+ fi
+ lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2
+ lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1
+ vgchange -an $vg1
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev1 $dev2
+ else
+ vgsplit -n $lv1 $vg1 $vg2
+ fi
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg2 4 2 1
+ else
+ aux vg_validate_pvlv_counts_ $vg2 2 2 1
+ fi
+ lvremove -f $vg2/$lv2
+ lvremove -f $vg2/$lv1
+ vgremove -f $vg2
+
+COMM "vgsplit correctly splits linear LV but not snap+origin LV into $i VG ($j args)"
+ vgcreate -c n $vg1 $dev1 $dev2
+ if [ $i = existing ]; then
+ vgcreate -c n $vg2 $dev3
+ fi
+ lvcreate -l 64 -i 2 -n $lv1 $vg1
+ lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1
+ vgextend $vg1 $dev4
+ lvcreate -l 64 -n $lv3 $vg1 $dev4
+ vgchange -an $vg1
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev4
+ else
+ vgsplit -n $lv3 $vg1 $vg2
+ fi
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg2 2 1 0
+ aux vg_validate_pvlv_counts_ $vg1 2 2 1
+ else
+ aux vg_validate_pvlv_counts_ $vg2 1 1 0
+ aux vg_validate_pvlv_counts_ $vg1 2 2 1
+ fi
+ lvremove -f $vg1/$lv2
+ lvremove -f $vg1/$lv1
+ lvremove -f $vg2/$lv3
+ vgremove -f $vg1
+ vgremove -f $vg2
+
+COMM "vgsplit correctly splits linear LV but not mirror LV into $i VG ($j args)"
+ vgcreate -c n $vg1 $dev1 $dev2 $dev3
+ if [ $i = existing ]; then
+ vgcreate -c n $vg2 $dev5
+ fi
+ lvcreate -l 64 -m1 -n $lv1 $vg1 $dev1 $dev2 $dev3
+ vgextend $vg1 $dev4
+ lvcreate -l 64 -n $lv2 $vg1 $dev4
+ vgchange -an $vg1
+ vgs
+ lvs
+ pvs
+ if [ $j = PV ]; then
+ vgsplit $vg1 $vg2 $dev4
+ else
+ vgsplit -n $lv2 $vg1 $vg2
+ fi
+ if [ $i = existing ]; then
+ aux vg_validate_pvlv_counts_ $vg1 3 1 0
+ aux vg_validate_pvlv_counts_ $vg2 2 1 0
+ else
+ vgs
+ lvs
+ pvs
+ aux vg_validate_pvlv_counts_ $vg1 3 1 0
+ aux vg_validate_pvlv_counts_ $vg2 1 1 0
+ fi
+ lvremove -f $vg1/$lv1
+ lvremove -f $vg2/$lv2
+ vgremove -f $vg1
+ vgremove -f $vg2
+
+ done
+done
+
+#
+# Test more complex setups where the code has to find associated PVs and
+# LVs to split the VG correctly
+#
+COMM "vgsplit fails splitting 3 striped LVs into VG when only 1 LV specified"
+vgcreate $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 -i 2 $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv2 -i 2 $vg1 $dev2 $dev3
+lvcreate -l 4 -n $lv3 -i 2 $vg1 $dev3 $dev4
+vgchange -an $vg1
+not vgsplit -n $lv1 $vg1 $vg2
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one LV with 2 snapshots, only origin LV specified"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv2 -s $vg1/$lv1 $dev3
+lvcreate -l 4 -n $lv3 -s $vg1/$lv1 $dev4
+vg_validate_pvlv_counts_ $vg1 4 3 2
+vgchange -an $vg1
+not vgsplit -n $lv1 $vg1 $vg2;
+lvremove -f $vg1/$lv2
+lvremove -f $vg1/$lv3
+lvremove -f $vg1/$lv1
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one LV with 2 snapshots, only snapshot LV specified"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv2 -s $vg1/$lv1 $dev3
+lvcreate -l 4 -n $lv3 -s $vg1/$lv1 $dev4
+vg_validate_pvlv_counts_ $vg1 4 3 2
+vgchange -an $vg1
+not vgsplit -n $lv2 $vg1 $vg2
+lvremove -f $vg1/$lv2
+lvremove -f $vg1/$lv3
+lvremove -f $vg1/$lv1
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting one mirror LV, only one PV specified"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3
+vg_validate_pvlv_counts_ $vg1 4 1 0
+vgchange -an $vg1
+not vgsplit $vg1 $vg2 $dev2
+vgremove -ff $vg1
+
+COMM "vgsplit fails splitting 1 mirror + 1 striped LV, only striped LV specified"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3
+lvcreate -l 16 -n $lv2 -i 2 $vg1 $dev3 $dev4
+vg_validate_pvlv_counts_ $vg1 4 2 0
+vgchange -an $vg1
+not vgsplit -n $lv2 $vg1 $vg2 2>err
+vgremove -ff $vg1
+
+#
+# Verify vgsplit rejects active LVs only when active LVs involved in split
+#
+COMM "vgsplit fails, active mirror involved in split"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3
+lvcreate -l 16 -n $lv2 $vg1 $dev4
+lvchange -an $vg1/$lv2
+vg_validate_pvlv_counts_ $vg1 4 2 0
+not vgsplit -n $lv1 $vg1 $vg2;
+vg_validate_pvlv_counts_ $vg1 4 2 0
+vgremove -ff $vg1
+
+COMM "vgsplit succeeds, active mirror not involved in split"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 16 -n $lv1 -m1 $vg1 $dev1 $dev2 $dev3
+lvcreate -l 16 -n $lv2 $vg1 $dev4
+lvchange -an $vg1/$lv2
+vg_validate_pvlv_counts_ $vg1 4 2 0
+vgsplit -n $lv2 $vg1 $vg2
+vg_validate_pvlv_counts_ $vg1 3 1 0
+vg_validate_pvlv_counts_ $vg2 1 1 0
+vgremove -ff $vg1
+vgremove -ff $vg2
+
+COMM "vgsplit fails, active snapshot involved in split"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3 $dev4
+lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2
+lvcreate -l 4 -i 2 -s -n $lv2 $vg1/$lv1
+lvcreate -l 64 -i 2 -n $lv3 $vg1 $dev3 $dev4
+lvchange -an $vg1/$lv3
+vg_validate_pvlv_counts_ $vg1 4 3 1
+not vgsplit -n $lv2 $vg1 $vg2;
+vg_validate_pvlv_counts_ $vg1 4 3 1
+lvremove -f $vg1/$lv2
+vgremove -ff $vg1
+
+COMM "vgsplit succeeds, active snapshot not involved in split"
+vgcreate -c n $vg1 $dev1 $dev2 $dev3
+lvcreate -l 64 -i 2 -n $lv1 $vg1 $dev1 $dev2
+lvcreate -l 4 -s -n $lv2 $vg1/$lv1
+vgextend $vg1 $dev4
+lvcreate -l 64 -n $lv3 $vg1 $dev4
+lvchange -an $vg1/$lv3
+vg_validate_pvlv_counts_ $vg1 4 3 1
+vgsplit -n $lv3 $vg1 $vg2
+vg_validate_pvlv_counts_ $vg1 3 2 1
+vg_validate_pvlv_counts_ $vg2 1 1 0
+vgchange -an $vg1
+lvremove -f $vg1/$lv2
+vgremove -ff $vg1
+vgremove -ff $vg2
+
diff --git a/test/t-vgsplit-stacked.sh b/test/t-vgsplit-stacked.sh
new file mode 100644
index 0000000..424156f
--- /dev/null
+++ b/test/t-vgsplit-stacked.sh
@@ -0,0 +1,28 @@
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. ./test-utils.sh
+
+prepare_lvmconf '[ "a/dev\/mirror/", "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]'
+aux prepare_devs 3
+
+pvcreate $devs
+vgcreate $vg1 $dev1 $dev2
+lvcreate -n $lv1 -l 100%FREE $vg1
+
+#top VG
+pvcreate $DM_DEV_DIR/$vg1/$lv1
+vgcreate $vg $DM_DEV_DIR/$vg1/$lv1 $dev3
+
+vgchange -a n $vg
+vgchange -a n $vg1
+
+# this should fail but not segfault, RHBZ 481793.
+not vgsplit $vg $vg1 $dev3
diff --git a/test/t-vgsplit-usage.sh b/test/t-vgsplit-usage.sh
new file mode 100755
index 0000000..ade39d8
--- /dev/null
+++ b/test/t-vgsplit-usage.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+# Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Test vgsplit command options for validity
+
+. ./test-utils.sh
+
+aux prepare_devs 5
+
+for mdatype in 1 2
+do
+
+pvcreate -M$mdatype $devs
+
+# ensure name order does not matter
+# NOTE: if we're using lvm1, we must use -M on vgsplit
+vgcreate -M$mdatype $vg1 $devs
+vgsplit -M$mdatype $vg1 $vg2 $dev1
+vgremove $vg1
+vgremove $vg2
+vgcreate -M$mdatype $vg2 $devs
+vgsplit -M$mdatype $vg2 $vg1 $dev1
+vgremove $vg1
+vgremove $vg2
+
+# vgsplit accepts new vg as destination of split
+# lvm1 -- bz244792
+vgcreate -M$mdatype $vg1 $devs
+vgsplit $vg1 $vg2 $dev1 1>err
+grep "New volume group \"$vg2\" successfully split from \"$vg1\"" err
+vgremove $vg1
+vgremove $vg2
+
+# vgsplit accepts existing vg as destination of split
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgcreate -M$mdatype $vg2 $dev3 $dev4
+vgsplit $vg1 $vg2 $dev1 1>err
+grep "Existing volume group \"$vg2\" successfully split from \"$vg1\"" err
+vgremove $vg1
+vgremove $vg2
+
+# vgsplit accepts --maxphysicalvolumes 128 on new VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgsplit --maxphysicalvolumes 128 $vg1 $vg2 $dev1
+check_vg_field_ $vg2 max_pv 128
+vgremove $vg1
+vgremove $vg2
+
+# vgsplit accepts --maxlogicalvolumes 128 on new VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgsplit --maxlogicalvolumes 128 $vg1 $vg2 $dev1
+check_vg_field_ $vg2 max_lv 128
+vgremove $vg1
+vgremove $vg2
+
+# vgsplit rejects split because max_pv of destination would be exceeded
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg2 $dev3 $dev4
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^ Maximum number of physical volumes (2) exceeded" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects split because maxphysicalvolumes given with existing vg
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate -M$mdatype --maxphysicalvolumes 2 $vg2 $dev3 $dev4
+not vgsplit --maxphysicalvolumes 2 $vg1 $vg2 $dev1 2>err;
+grep "^ Volume group \"$vg2\" exists, but new VG option specified" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects split because maxlogicalvolumes given with existing vg
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg2 $dev3 $dev4
+not vgsplit --maxlogicalvolumes 2 $vg1 $vg2 $dev1 2>err
+grep "^ Volume group \"$vg2\" exists, but new VG option specified" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects split because alloc given with existing vg
+vgcreate -M$mdatype --alloc cling $vg1 $dev1 $dev2
+vgcreate -M$mdatype --alloc cling $vg2 $dev3 $dev4
+not vgsplit --alloc cling $vg1 $vg2 $dev1 2>err;
+grep "^ Volume group \"$vg2\" exists, but new VG option specified" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects split because clustered given with existing vg
+vgcreate -M$mdatype --clustered n $vg1 $dev1 $dev2
+vgcreate -M$mdatype --clustered n $vg2 $dev3 $dev4
+not vgsplit --clustered n $vg1 $vg2 $dev1 2>err
+grep "^ Volume group \"$vg2\" exists, but new VG option specified" err
+vgremove $vg2
+vgremove $vg1
+
+# vgsplit rejects vg with active lv
+pvcreate -M$mdatype -ff $dev3 $dev4
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgcreate -M$mdatype $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^ Logical volumes in \"$vg1\" must be inactive\$" err
+vgremove -f $vg2
+vgremove -f $vg1
+
+# vgsplit rejects split because max_lv is exceeded
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg1 $dev1 $dev2
+vgcreate -M$mdatype --maxlogicalvolumes 2 $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv2 $vg1
+lvcreate -l 4 -n $lv3 $vg2
+vgchange -an $vg1
+vgchange -an $vg2
+not vgsplit $vg1 $vg2 $dev1 2>err;
+grep "^ Maximum number of logical volumes (2) exceeded" err
+vgremove -f $vg2
+vgremove -f $vg1
+
+# vgsplit verify default - max_lv attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv1 $vg1
+vgchange -an $vg1
+vgsplit $vg1 $vg2 $dev1
+compare_vg_field_ $vg1 $vg2 max_lv
+vgremove -f $vg2
+vgremove -f $vg1
+
+# vgsplit verify default - max_pv attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv1 $vg1
+vgchange -an $vg1
+vgsplit $vg1 $vg2 $dev1
+compare_vg_field_ $vg1 $vg2 max_pv
+vgremove -f $vg2
+vgremove -f $vg1
+
+# vgsplit verify default - vg_fmt attribute from new VG is same as source VG" \
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+lvcreate -l 4 -n $lv1 $vg1
+vgchange -an $vg1
+vgsplit $vg1 $vg2 $dev1
+compare_vg_field_ $vg1 $vg2 vg_fmt
+vgremove -f $vg2
+vgremove -f $vg1
+
+# vgsplit rejects split because PV not in VG
+vgcreate -M$mdatype $vg1 $dev1 $dev2
+vgcreate -M$mdatype $vg2 $dev3 $dev4
+lvcreate -l 4 -n $lv1 $vg1
+lvcreate -l 4 -n $lv2 $vg1
+vgchange -an $vg1
+not vgsplit $vg1 $vg2 $dev3 2>err;
+vgremove -f $vg2
+vgremove -f $vg1
+done
+
+# ONLY LVM2 metadata
+# setup PVs" '
+pvcreate --metadatacopies 0 $dev5
+
+# vgsplit rejects to give away pv with the last mda copy
+vgcreate $vg1 $dev5 $dev2
+lvcreate -l 10 -n $lv1 $vg1
+lvchange -an $vg1/$lv1
+vg_validate_pvlv_counts_ $vg1 2 1 0
+not vgsplit $vg1 $vg2 $dev5;
+vg_validate_pvlv_counts_ $vg1 2 1 0
+vgremove -ff $vg1
+
+# vgsplit rejects split because metadata types differ
+pvcreate -ff -M1 $dev3 $dev4
+pvcreate -ff $dev1 $dev2
+vgcreate -M1 $vg1 $dev3 $dev4
+vgcreate $vg2 $dev1 $dev2
+not vgsplit $vg1 $vg2 $dev3 2>err;
+grep "^ Metadata types differ" err
+vgremove $vg2
+vgremove $vg1
+
diff --git a/test/test-utils.sh b/test/test-utils.sh
new file mode 100644
index 0000000..e1aea8a
--- /dev/null
+++ b/test/test-utils.sh
@@ -0,0 +1,457 @@
+# Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+aux() {
+ # use just "$@" for verbose operation
+ "$@" > /dev/null 2> /dev/null
+ #"$@"
+}
+
+STACKTRACE() {
+ trap - ERR;
+ i=0;
+
+ while FUNC=${FUNCNAME[$i]}; test "$FUNC" != "main"; do
+ echo "$i ${FUNC}() called from ${BASH_SOURCE[$i]}:${BASH_LINENO[$i]}"
+ i=$(($i + 1));
+ done
+
+ # Get backtraces from coredumps
+ if which gdb >& /dev/null; then
+ echo bt full > gdb_commands.txt
+ echo l >> gdb_commands.txt
+ echo quit >> gdb_commands.txt
+ for core in `ls core* 2>/dev/null`; do
+ bin=$(gdb -batch -c $core 2>&1 | grep "generated by" | \
+ sed -e "s,.*generated by \`\([^ ']*\).*,\1,")
+ gdb -batch -c $core -x gdb_commands.txt `which $bin`
+ done
+ fi
+
+ test -f debug.log && {
+ sed -e "s,^,## DEBUG: ,;s,$top_srcdir/\?,," < debug.log
+ }
+}
+
+init_udev_transaction() {
+ if test "$DM_UDEV_SYNCHRONISATION" = 1; then
+ COOKIE=$(dmsetup udevcreatecookie)
+ # Cookie is not generated if udev is not running!
+ if test -n "$COOKIE"; then
+ export DM_UDEV_COOKIE=$COOKIE
+ fi
+ fi
+}
+
+finish_udev_transaction() {
+ if test "$DM_UDEV_SYNCHRONISATION" = 1 -a -n "$DM_UDEV_COOKIE"; then
+ dmsetup udevreleasecookie
+ unset DM_UDEV_COOKIE
+ fi
+}
+
+prepare_clvmd() {
+ if test -z "$LVM_TEST_LOCKING" || test "$LVM_TEST_LOCKING" -ne 3 ; then
+ return 0 # not needed
+ fi
+
+ if pgrep clvmd ; then
+ echo "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running."
+ exit 200
+ fi
+
+ # skip if we don't have our own clvmd...
+ (which clvmd | grep $abs_builddir) || exit 200
+
+ # skip if we singlenode is not compiled in
+ (clvmd --help 2>&1 | grep "Available cluster managers" | grep singlenode) || exit 200
+
+ trap_teardown
+
+ clvmd -Isinglenode -d 1 &
+ LOCAL_CLVMD="$!"
+
+ # check that it is really running now
+ sleep .1
+ ps $LOCAL_CLVMD || exit 200
+}
+
+prepare_dmeventd() {
+ if pgrep dmeventd ; then
+ echo "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running."
+ exit 200
+ fi
+
+ # skip if we don't have our own dmeventd...
+ (which dmeventd | grep $abs_builddir) || exit 200
+
+ trap_teardown
+
+ dmeventd -f &
+ LOCAL_DMEVENTD="$!"
+}
+
+prepare_testroot() {
+ OLDPWD="`pwd`"
+ PREFIX="LVMTEST$$"
+
+ trap_teardown
+ TESTDIR=$($abs_srcdir/mkdtemp ${LVM_TEST_DIR-$(pwd)} $PREFIX.XXXXXXXXXX) \
+ || { echo "failed to create temporary directory in ${LVM_TEST_DIR-$(pwd)}"; exit 1; }
+
+ export LVM_SYSTEM_DIR=$TESTDIR/etc
+ export DM_DEV_DIR=$TESTDIR/dev
+ mkdir $LVM_SYSTEM_DIR $DM_DEV_DIR $DM_DEV_DIR/mapper $TESTDIR/lib
+
+ cd $TESTDIR
+
+ for i in `find $abs_top_builddir/daemons/dmeventd/plugins/ -name \*.so`; do
+ echo Setting up symlink from $i to $TESTDIR/lib
+ ln -s $i $TESTDIR/lib
+ done
+}
+
+teardown_devs() {
+ test -n "$PREFIX" && {
+ rm -rf $TESTDIR/dev/$PREFIX*
+
+ init_udev_transaction
+ while dmsetup table | grep -q ^$PREFIX; do
+ for s in `dmsetup info -c -o name --noheading | grep ^$PREFIX`; do
+ umount -fl $DM_DEV_DIR/mapper/$s || true
+ dmsetup remove $s >& /dev/null || true
+ done
+ done
+ finish_udev_transaction
+
+ }
+
+ # NOTE: SCSI_DEBUG_DEV test must come before the LOOP test because
+ # prepare_scsi_debug_dev() also sets LOOP to short-circuit prepare_loop()
+ if [ -n "$SCSI_DEBUG_DEV" ] ; then
+ modprobe -r scsi_debug
+ else
+ test -n "$LOOP" && losetup -d $LOOP
+ test -n "$LOOPFILE" && rm -f $LOOPFILE
+ fi
+ unset devs # devs is set in prepare_devs()
+ unset LOOP
+}
+
+teardown() {
+ echo $LOOP
+ echo $PREFIX
+
+ test -n "$LOCAL_CLVMD" && {
+ kill "$LOCAL_CLVMD"
+ sleep .1
+ kill -9 "$LOCAL_CLVMD" || true
+ }
+
+ test -n "$LOCAL_DMEVENTD" && kill -9 "$LOCAL_DMEVENTD"
+
+ teardown_devs
+
+ test -n "$TESTDIR" && {
+ cd $OLDPWD
+ rm -rf $TESTDIR || echo BLA
+ }
+}
+
+trap_teardown() {
+ trap 'set +vx; STACKTRACE; set -vx' ERR
+ trap 'aux teardown' EXIT # don't forget to clean up
+}
+
+make_ioerror() {
+ echo 0 10000000 error | dmsetup create ioerror
+ ln -s $DM_DEV_DIR/mapper/ioerror $DM_DEV_DIR/ioerror
+}
+
+prepare_loop() {
+ size=$1
+ test -n "$size" || size=32
+
+ # skip if prepare_scsi_debug_dev() was used
+ if [ -n "$SCSI_DEBUG_DEV" -a -n "$LOOP" ]; then
+ return 0
+ fi
+
+ test -z "$LOOP"
+ test -n "$DM_DEV_DIR"
+
+ trap_teardown
+
+ for i in 0 1 2 3 4 5 6 7; do
+ test -e $DM_DEV_DIR/loop$i || mknod $DM_DEV_DIR/loop$i b 7 $i
+ done
+
+ LOOPFILE="$PWD/test.img"
+ dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=0 seek=$(($size-1))
+ if LOOP=`losetup -s -f "$LOOPFILE" 2>/dev/null`; then
+ return 0
+ elif LOOP=`losetup -f` && losetup $LOOP "$LOOPFILE"; then
+ # no -s support
+ return 0
+ else
+ # no -f support
+ # Iterate through $DM_DEV_DIR/loop{,/}{0,1,2,3,4,5,6,7}
+ for slash in '' /; do
+ for i in 0 1 2 3 4 5 6 7; do
+ local dev=$DM_DEV_DIR/loop$slash$i
+ ! losetup $dev >/dev/null 2>&1 || continue
+ # got a free
+ losetup "$dev" "$LOOPFILE"
+ LOOP=$dev
+ break
+ done
+ if [ -n "$LOOP" ]; then
+ break
+ fi
+ done
+ test -n "$LOOP" # confirm or fail
+ return 0
+ fi
+ exit 1 # should not happen
+}
+
+# A drop-in replacement for prepare_loop() that uses scsi_debug to create
+# a ramdisk-based SCSI device upon which all LVM devices will be created
+# - scripts must take care not to use a DEV_SIZE that will enduce OOM-killer
+prepare_scsi_debug_dev()
+{
+ local DEV_SIZE="$1"
+ shift
+ local SCSI_DEBUG_PARAMS="$@"
+
+ test -n "$SCSI_DEBUG_DEV" && return 0
+ test -z "$LOOP"
+ test -n "$DM_DEV_DIR"
+
+ trap_teardown
+
+ # Skip test if awk isn't available (required for get_sd_devs_)
+ which awk || exit 200
+
+ # Skip test if scsi_debug module is unavailable or is already in use
+ modprobe --dry-run scsi_debug || exit 200
+ lsmod | grep -q scsi_debug && exit 200
+
+ # Create the scsi_debug device and determine the new scsi device's name
+ # NOTE: it will _never_ make sense to pass num_tgts param;
+ # last param wins.. so num_tgts=1 is imposed
+ modprobe scsi_debug dev_size_mb=$DEV_SIZE $SCSI_DEBUG_PARAMS num_tgts=1 || exit 200
+ sleep 2 # allow for async Linux SCSI device registration
+
+ local DEBUG_DEV=/dev/$(grep -H scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $DEBUG_DEV ] || exit 1 # should not happen
+
+ # Create symlink to scsi_debug device in $DM_DEV_DIR
+ SCSI_DEBUG_DEV=$DM_DEV_DIR/$(basename $DEBUG_DEV)
+ # Setting $LOOP provides means for prepare_devs() override
+ LOOP=$SCSI_DEBUG_DEV
+ ln -snf $DEBUG_DEV $SCSI_DEBUG_DEV
+ return 0
+}
+
+cleanup_scsi_debug_dev()
+{
+ aux teardown_devs
+ unset SCSI_DEBUG_DEV
+ unset LOOP
+}
+
+prepare_devs() {
+ local n="$1"
+ test -z "$n" && n=3
+ local devsize="$2"
+ test -z "$devsize" && devsize=34
+ local pvname="$3"
+ test -z "$pvname" && pvname="pv"
+
+ prepare_loop $(($n*$devsize))
+
+ if ! loopsz=`blockdev --getsz $LOOP 2>/dev/null`; then
+ loopsz=`blockdev --getsize $LOOP 2>/dev/null`
+ fi
+
+ local size=$(($loopsz/$n))
+
+ init_udev_transaction
+ for i in `seq 1 $n`; do
+ local name="${PREFIX}$pvname$i"
+ local dev="$DM_DEV_DIR/mapper/$name"
+ eval "dev$i=$dev"
+ devs="$devs $dev"
+ echo 0 $size linear $LOOP $((($i-1)*$size)) > $name.table
+ dmsetup create $name $name.table
+ done
+ finish_udev_transaction
+
+ for i in `seq 1 $n`; do
+ local name="${PREFIX}$pvname$i"
+ dmsetup info -c $name
+ done
+ for i in `seq 1 $n`; do
+ local name="${PREFIX}$pvname$i"
+ dmsetup table $name
+ done
+}
+
+disable_dev() {
+
+ init_udev_transaction
+ for dev in "$@"; do
+ # first we make the device inaccessible
+ echo 0 10000000 error | dmsetup load $dev
+ dmsetup resume $dev
+ # now let's try to get rid of it if it's unused
+ #dmsetup remove $dev
+ done
+ finish_udev_transaction
+
+}
+
+enable_dev() {
+
+ init_udev_transaction
+ for dev in "$@"; do
+ local name=`echo "$dev" | sed -e 's,.*/,,'`
+ dmsetup create $name $name.table || dmsetup load $name $name.table
+ dmsetup resume $dev
+ done
+ finish_udev_transaction
+}
+
+backup_dev() {
+ for dev in "$@"; do
+ dd if=$dev of=$dev.backup bs=1024
+ done
+}
+
+restore_dev() {
+ for dev in "$@"; do
+ test -e $dev.backup || {
+ echo "Internal error: $dev not backed up, can't restore!"
+ exit 1
+ }
+ dd of=$dev if=$dev.backup bs=1024
+ done
+}
+
+prepare_pvs() {
+ prepare_devs "$@"
+ pvcreate -ff $devs
+}
+
+prepare_vg() {
+ vgremove -ff $vg || true
+ teardown_devs
+
+ prepare_pvs "$@"
+ vgcreate -c n $vg $devs
+ pvs -v
+}
+
+prepare_lvmconf() {
+ local filter="$1"
+ test -z "$filter" && \
+ filter='[ "a/dev\/mirror/", "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]'
+ locktype=
+ if test -z "$LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND"; then
+ LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND="
+ snapshot_autoextend_percent = 50
+ snapshot_autoextend_threshold = 50"
+ fi
+ if test -n "$LVM_TEST_LOCKING"; then locktype="locking_type = $LVM_TEST_LOCKING"; fi
+ cat > $TESTDIR/etc/lvm.conf.new <<-EOF
+ $LVM_TEST_CONFIG
+ devices {
+ dir = "$DM_DEV_DIR"
+ scan = "$DM_DEV_DIR"
+ filter = $filter
+ cache_dir = "$TESTDIR/etc"
+ sysfs_scan = 0
+ default_data_alignment = 1
+ $LVM_TEST_CONFIG_DEVICES
+ }
+ log {
+ syslog = 0
+ indent = 1
+ level = 9
+ file = "$TESTDIR/debug.log"
+ overwrite = 1
+ activation = 1
+ }
+ backup {
+ backup = 0
+ archive = 0
+ }
+ global {
+ abort_on_internal_errors = 1
+ library_dir = "$TESTDIR/lib"
+ locking_dir = "$TESTDIR/var/lock/lvm"
+ $locktype
+ si_unit_consistency = 1
+ fallback_to_local_locking = 0
+ }
+ activation {
+ udev_sync = 1
+ udev_rules = 1
+ polling_interval = 0
+ $LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND
+ }
+EOF
+ # FIXME remove this workaround after mmap & truncating file problems solved
+ mv -f $TESTDIR/etc/lvm.conf.new $TESTDIR/etc/lvm.conf
+ cat $TESTDIR/etc/lvm.conf
+}
+
+prepare() {
+ ulimit -c unlimited
+ # FIXME any way to set this just for our children?
+ # echo 1 > /proc/sys/kernel/core_uses_pid
+ prepare_testroot
+ prepare_lvmconf
+ prepare_clvmd
+
+ # set up some default names
+ vg=${PREFIX}vg
+ vg1=${PREFIX}vg1
+ vg2=${PREFIX}vg2
+ lv=LV
+ lv1=LV1
+ lv2=LV2
+ lv3=LV3
+ lv4=LV4
+}
+
+apitest() {
+ t=$1
+ shift
+ test -x $abs_top_builddir/test/api/$t.t || exit 200
+ $abs_top_builddir/test/api/$t.t "$@"
+}
+
+api() {
+ test -x $abs_top_builddir/test/api/wrapper || exit 200
+ $abs_top_builddir/test/api/wrapper "$@"
+}
+
+LANG=C
+LC_ALL=C
+TZ=UTC
+unset CDPATH
+
+. ./init.sh || { echo >&2 you must run make first; exit 1; }
+. ./lvm-utils.sh
+
+set -vexE -o pipefail
+aux prepare