diff options
author | Anas Nashif <anas.nashif@intel.com> | 2013-03-05 01:43:20 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-03-05 01:43:20 -0800 |
commit | 8bd28eea831fd5215c12e6fcecc8e9a772398ed9 (patch) | |
tree | 2579ba0d9921953cadfc17006c47ff419382898a /test | |
download | device-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')
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 |